home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / pictex / pictex.tex (.txt) < prev    next >
LaTeX Document  |  1992-08-26  |  130KB  |  3,249 lines

  1. % This is PiCTeX, Version 1.1   9/21/87
  2. % CAVEAT: The PiCTeX manual often has a more lucid explanation
  3. %   of any given topic than you will find in the internal documentation
  4. %   of the macros.
  5. % PiCTeX's commands can be classified into two groups: (1) public (or
  6. %   external), and (2) private (or internal). The public macros are
  7. %   discussed at length in the manual. The only discussion of the private
  8. %   macros is the internal documentation. The private macros all have
  9. %   names beginning with an exclamation point (!) of category code 11. 
  10. %   Since in normal usage "!" has category code 12, these macros can't
  11. %   be accessed or modified by the general user.
  12. % The macros are organized into thematically related groups. For example,
  13. %   the macros dealing with dots & dashes are all in the DASHPATTERN group.
  14. %   The table below shows which macros are in which groups. The table
  15. %   covers all public macros, and many (but not all) of PiCTeX's upper level
  16. %   private macros. Following the table, the various groups are listed
  17. %   in the order in which they appear in the table.
  18. % *********************** TABLE OF GROUPS OF MACROS **********************
  19. % HACKS:  Utility macros
  20. %    \PiC
  21. %    \PiCTeX
  22. %    \placevalueinpts 
  23. %    \!!loop 
  24. %    \!cfor
  25. %    \!copylist
  26. %    \!ecfor
  27. %    \!etfor
  28. %    \!getnext
  29. %    \!getnextvalueof
  30. %    \!ifempty
  31. %    \!ifnextchar
  32. %    \!leftappend
  33. %    \!listaddon 
  34. %    \!loop
  35. %    \!lop
  36. %    \!mlap
  37. %    \!not
  38. %    \!removept
  39. %    \!rightappend
  40. %    \!tfor 
  41. %    \!vmlap
  42. %    \!wlet
  43. % ALLOCATION:  Allocates registers
  44. % AREAS: Deals with plot areas 
  45. %    \axis
  46. %    \grid 
  47. %    \invisibleaxes
  48. %    \normalgraphs 
  49. %    \plotheading 
  50. %    \setplotarea
  51. %    \visibleaxes
  52. % ARROWS:  Draws arrows
  53. %    \arrow
  54. %    \betweenarrows
  55. % BARS:  Draws bars
  56. %    \putbar 
  57. %    \setbars
  58. % BOXES:  Draws rectangles
  59. %    \frame
  60. %    \putrectangle 
  61. %    \rectangle
  62. %    \shaderectangleson
  63. %    \shaderectanglesoff
  64. % CURVES:  Upper level plot commands
  65. %    \hshade 
  66. %    \plot 
  67. %    \sethistograms
  68. %    \setlinear
  69. %    \setquadratic
  70. %    \vshade
  71. % DASHPATTERNS:  Sets up dash patterns
  72. %    \findlength 
  73. %    \setdashes 
  74. %    \setdashesnear
  75. %    \setdashpattern
  76. %    \setdots 
  77. %    \setdotsnear 
  78. %    \setsolid
  79. %    \!dashingoff
  80. %    \!dashingon
  81. % DIVISION:  Does long division of dimension registers
  82. %    \Divide 
  83. %    \!divide
  84. % ELLIPSES:  Draws ellipses and circles
  85. %    \circulararc 
  86. %    \ellipticalarc 
  87. % RULES:  Draws rules, i.e., horizontal & vertical lines
  88. %    \putrule 
  89. %    \!putdashedhline
  90. %    \!putdashedvline
  91. %    \!puthline 
  92. %    \!putsolidhline  
  93. %    \!putsolidvline  
  94. %    \!putvline
  95. % LINEAR ARC:  Draws straight lines -- solid and dashed
  96. %    \inboundscheckoff
  97. %    \inboundscheckon
  98. %    \!advancedashing 
  99. %    \!drawlinearsegment
  100. %    \!initinboundscheck
  101. %    \!linearsolid
  102. %    \!lineardashed
  103. %    \!ljoin
  104. %    \!plotifinbounds     
  105. %    \!start 
  106. % LOGTEN:  Log_10 function
  107. %    \!logten
  108. % PICTURES:  Basic setups for PiCtures; \put commands
  109. %    \accountingoff
  110. %    \accountingon
  111. %    \beginpicture
  112. %    \endpicture    
  113. %    \endpicturesave 
  114. %    \lines
  115. %    \multiput
  116. %    \put 
  117. %    \setcoordinatemode
  118. %    \setcoordinatesystem
  119. %    \setdimensionmode
  120. %    \stack 
  121. %    \Lines
  122. %    \Xdistance
  123. %    \Ydistance
  124. %    \!dimenput
  125. %    \!ifcoordmode
  126. %    \!ifdimenmode
  127. %    \!setcoordmode
  128. %    \!setdimenmode
  129. %    \!setputobject
  130. % PLOTTING:  Things to do with plotting
  131. %    \dontsavelinesandcurves
  132. %    \replot
  133. %    \savelinesandcurves 
  134. %    \setplotsymbol
  135. %    \writesavefile 
  136. %    \!plot
  137. % PYTHAGORAS:  Euclidean distance function
  138. %    \placehypotenuse 
  139. %    \!Pythag
  140. % QUADRATIC ARC:  Draws a quadratic arc
  141. %    \!qjoin 
  142. % ROTATIONS:  Handles rotations
  143. %    \startrotation 
  144. %    \stoprotation
  145. %    \!rotateaboutpivot
  146. %    \!rotateonly
  147. % SHADING:  Handles shading
  148. %    \setshadegrid 
  149. %    \setshadesymbol
  150. %    \!lshade
  151. %    \!qshade
  152. %    \!starthshade
  153. %    \!startvshade  
  154. % TICKS:  Draws ticks on graphs
  155. %    \gridlines
  156. %    \loggedticks
  157. %    \nogridlines
  158. %    \ticksin
  159. %    \ticksout
  160. %    \unloggesticks
  161. % ***************** END OF TABLE OF GROUPS OF MACROS ********************
  162. \catcode`!=11 %  ***** THIS MUST NEVER BE OMITTED
  163. % *******************************
  164. % *** HACKS  (Utility macros) ***
  165. % *******************************
  166. % ** User commands
  167. % **   \PiC{P\kern-.12em\lower.5ex\hbox{I}\kern-.075emC}
  168. % **   \PiCTeX{\PiC\kern-.11em\TeX}
  169. % **   \placevalueinpts of <DIMENSION REGISTER> in {CONTROL SEQUENCE}
  170. % ** Internal commands
  171. % **   \!ifnextchar{CHARACTER}{TRUE ACTION}{FALSE ACTION}
  172. % **   \!tfor NAME := LIST \do {BODY}
  173. % **   \!etfor NAME:= LIST \do {BODY}
  174. % **   \!cfor NAME := LIST \do {BODY}
  175. % **   \!ecfor NAME:= LIST \do {BODY}
  176. % **   \!ifempty{MACRO}{TRUE ACTION}{FALSE ACTION}
  177. % **   \!getnext\\ITEMfrom\LIST
  178. % **   \!getnextvalueof\DIMEN\from\LIST
  179. % **   \!copylist\LISTMACRO_A\to\LISTMACRO_B
  180. % **   \!wlet\CONTROL_SEQUENCE_A=\CONTROL_SEQUENCE_B
  181. % **   \!listaddon ITEM LIST
  182. % **   \!rightappendITEM\withCS\to\LISTMACRO
  183. % **   \!leftappendITEM\withCS\to\LISTMACRO
  184. % **   \!lop\LISTMACRO\to\ITEM
  185. % **   \!loop ... repeat
  186. % **   \!!loop ... repeat
  187. % **   \!removept{DIMENSION REGISTER}{CONTROL SEQUENCE}
  188. % **   \!mlap{...}  
  189. % **   \!vmlap{...}
  190. % **   \!not{TEK if-CONDITION}
  191. % ** First, here are the the PiCTeX logo, and the syllable PiC:
  192. \def\PiC{P\kern-.12em\lower.5ex\hbox{I}\kern-.075emC}
  193. \def\PiCTeX{\PiC\kern-.11em\TeX}
  194. % ** The following macro expands to parameter #2 or parameter #3 according to
  195. % ** whether the next non-blank character following the macro is or is not #1. 
  196. % ** Blanks following the macro are gobbled.
  197. \def\!ifnextchar#1#2#3{%
  198.   \let\!testchar=#1%
  199.   \def\!first{#2}%
  200.   \def\!second{#3}%
  201.   \futurelet\!nextchar\!testnext}
  202. \def\!testnext{%
  203.   \ifx \!nextchar \!spacetoken 
  204.     \let\!next=\!skipspacetestagain
  205.   \else
  206.     \ifx \!nextchar \!testchar
  207.       \let\!next=\!first
  208.     \else 
  209.       \let\!next=\!second 
  210.     \fi 
  211.   \fi
  212.   \!next}
  213. \def\\{\!skipspacetestagain} 
  214.   \expandafter\def\\ {\futurelet\!nextchar\!testnext} 
  215. \def\\{\let\!spacetoken= } \\  %  ** set \spacetoken to a space token
  216. % ** Borrow the "tfor" macro from Latex:
  217. % **   \!tfor NAME := LIST \do {BODY}
  218. % **   if, before expansion, LIST = T1 ... Tn,  where each  Ti  is a token
  219. % **   or  {...},  then executes  BODY  n  times, with  NAME = Ti  on the
  220. % **   i-th iteration.  Works for  n=0.
  221. \def\!tfor#1:=#2\do#3{%
  222.   \edef\!fortemp{#2}%
  223.   \ifx\!fortemp\!empty 
  224.     \else
  225.     \!tforloop#2\!nil\!nil\!!#1{#3}%
  226.   \fi}
  227. \def\!tforloop#1#2\!!#3#4{%
  228.   \def#3{#1}%
  229.   \ifx #3\!nnil
  230.     \let\!nextwhile=\!fornoop
  231.   \else
  232.     #4\relax
  233.     \let\!nextwhile=\!tforloop
  234.   \fi 
  235.   \!nextwhile#2\!!#3{#4}}
  236. % **   \!etfor NAME:= LIST\do {BODY}
  237. % **   This is like \!cfor, but LIST is any balanced token list whose complete
  238. % **     expansion has the form  T1 ... Tn
  239. \def\!etfor#1:=#2\do#3{%
  240.   \def\!!tfor{\!tfor#1:=}%
  241.   \edef\!!!tfor{#2}%
  242.   \expandafter\!!tfor\!!!tfor\do{#3}}
  243. % **   modify the Latex \tfor (token-for) loop to a \cfor (comma-for) loop.
  244. % **   \!cfor NAME := LIST \do {BODY}
  245. % **     if, before expansion, LIST = a1,a2,...an, then executes  BODY n times,
  246. % **     with  NAME = ai  on the i-th iteration.  Works for  n=0.
  247. \def\!cfor#1:=#2\do#3{%
  248.   \edef\!fortemp{#2}%
  249.   \ifx\!fortemp\!empty 
  250.   \else
  251.     \!cforloop#2,\!nil,\!nil\!!#1{#3}%
  252.   \fi}
  253. \def\!cforloop#1,#2\!!#3#4{%
  254.   \def#3{#1}%
  255.   \ifx #3\!nnil
  256.     \let\!nextwhile=\!fornoop 
  257.   \else
  258.     #4\relax
  259.     \let\!nextwhile=\!cforloop
  260.   \fi
  261.   \!nextwhile#2\!!#3{#4}}
  262. % **   \!ecfor NAME:= LIST\do {BODY}
  263. % **   This is like \!cfor, but LIST is any balanced token list whose complete
  264. % **     expansion has the form  a1,a2,...,an.
  265. \def\!ecfor#1:=#2\do#3{%
  266.   \def\!!cfor{\!cfor#1:=}%
  267.   \edef\!!!cfor{#2}%
  268.   \expandafter\!!cfor\!!!cfor\do{#3}}
  269. \def\!empty{}
  270. \def\!nnil{\!nil}
  271. \def\!fornoop#1\!!#2#3{}
  272. % **  \!ifempty{ARG}{TRUE ACTION}{FALSE ACTION}
  273. \def\!ifempty#1#2#3{%
  274.   \edef\!emptyarg{#1}%
  275.   \ifx\!emptyarg\!empty
  276.     #2%
  277.   \else
  278.     #3%
  279.   \fi}
  280. % **  \!getnext\\ITEMfrom\LIST
  281. % **    \LIST has the form \\{item1}\\{item2}\\{item3}...\\{itemk}
  282. % **    This routine sets \ITEM to item1, and cycles \LIST to
  283. % **    \\{item2}\\{item3}...\\{itemk}\\{item1}
  284. \def\!getnext#1\from#2{%
  285.   \expandafter\!gnext#2\!#1#2}%
  286. \def\!gnext\\#1#2\!#3#4{%
  287.   \def#3{#1}%
  288.   \def#4{#2\\{#1}}%
  289.   \ignorespaces}
  290. % ** \!getnextvalueof\DIMEN\from\LIST
  291. % **   Similar to !getnext.  
  292. % **   \LIST has the form \\{dimen1}\\{dimen2}\\{dimen3} ... 
  293. % **   \DIMEN is a dimension register
  294. % **   Works also for counts
  295. \def\!getnextvalueof#1\from#2{%
  296.   \expandafter\!gnextv#2\!#1#2}%
  297. \def\!gnextv\\#1#2\!#3#4{%
  298.   #3=#1%
  299.   \def#4{#2\\{#1}}%
  300.   \ignorespaces}
  301. % ** \!copylist\LISTMACROA\to\LISTMACROB
  302. % **   makes the replacement text of LISTMACRO B identical to that of
  303. % **   list macro A.
  304. \def\!copylist#1\to#2{%
  305.   \expandafter\!!copylist#1\!#2}
  306. \def\!!copylist#1\!#2{%
  307.   \def#2{#1}\ignorespaces}
  308. % **  \!wlet\CSA=\CSB
  309. % **  lets control sequence \CSB = control sequence \CSA, and writes a
  310. % **    message to that effect in the log file using plain TEK's \wlog
  311. \def\!wlet#1=#2{%
  312.   \let#1=#2 
  313.   \wlog{\string#1=\string#2}}
  314. % ** \!listaddon ITEM LIST
  315. % ** LIST <-- LIST \\ ITEM
  316. \def\!listaddon#1#2{%
  317.   \expandafter\!!listaddon#2\!{#1}#2}
  318. \def\!!listaddon#1\!#2#3{%
  319.   \def#3{#1\\#2}}
  320. % **  \!rightappendITEM\to\LISTMACRO
  321. % **    \LISTMACRO --> \LISTMACRO\\{ITEM}
  322. %\def\!rightappend#1\to#2{\expandafter\!!rightappend#2\!{#1}#2}
  323. %\def\!!rightappend#1\!#2#3{\def#3{#1\\{#2}}}
  324. % **  \!rightappendITEM\withCS\to\LISTMACRO
  325. % **    \LISTMACRO --> \LISTMACRO||CS||{ITEM}
  326. \def\!rightappend#1\withCS#2\to#3{\expandafter\!!rightappend#3\!#2{#1}#3}
  327. \def\!!rightappend#1\!#2#3#4{\def#4{#1#2{#3}}}
  328. % **  \!leftappendITEM\withCS\to\LISTMACRO
  329. % **    \LISTMACRO --> CS||{ITEM}||\LISTMACRO
  330. \def\!leftappend#1\withCS#2\to#3{\expandafter\!!leftappend#3\!#2{#1}#3}
  331. \def\!!leftappend#1\!#2#3#4{\def#4{#2{#3}#1}}
  332. % **  \!lop\LISTMACRO\to\ITEM
  333. % **    \\{item1}\\{item2}\\{item3} ... --> \\{item2}\\{item3} ...
  334. % **    item1 --> \ITEM
  335. \def\!lop#1\to#2{\expandafter\!!lop#1\!#1#2}
  336. \def\!!lop\\#1#2\!#3#4{\def#4{#1}\def#3{#2}}
  337. % **  \!placeNUMBER\of\LISTMACRO\in\ITEM
  338. % **    the NUMBERth item of \LISTMACRO --> replacement text of \ITEM
  339. %\def\!place#1\of#2\in#3{\def#3{\outofrange}%
  340. %{\count0=#1\def\\##1{\advance\count0-1 \ifnum\count0=0 \gdef#3{##1}\fi}#2}}
  341. % **  Following code converts a commalist to a list macro, with all items 
  342. % **    fully expanded.
  343. %\!ecfor\item:=\commalist\do{\expandafter\!rightappend\item\to\list}
  344. % ** \!loop ... repeat
  345. % ** This is exactly like TEX's \loop ... repeat.  It can be used in nesting
  346. % ** two loops, without puting the inner one inside a group.
  347. \def\!loop#1\repeat{\def\!body{#1}\!iterate}
  348. \def\!iterate{\!body\let\!next=\!iterate\else\let\!next=\relax\fi\!next}
  349. % ** \!!loop ... repeat
  350. % ** This is exactly like TEX's \loop ... repeat.  It can be used in nesting
  351. % ** two loops, without puting the inner one inside a group.
  352. \def\!!loop#1\repeat{\def\!!body{#1}\!!iterate}
  353. \def\!!iterate{\!!body\let\!!next=\!!iterate\else\let\!!next=\relax\fi\!!next}
  354. %  (\multiput uses \!!loop)
  355. % ** \!removept{DIMENREG}{\CS}
  356. % ** Defines the control sequence CS to be the value (in points) in the
  357. % ** dimension register DIMENREG (but without the "pt" TEK usually adds)
  358. % ** E.g., after  \dimen0=12.3pt \!removept\dimen0\A, \A expands to 12.3
  359. \def\!removept#1#2{\edef#2{\expandafter\!!removePT\the#1}}
  360. {\catcode`p=12 \catcode`t=12 \gdef\!!removePT#1pt{#1}}
  361. % ** \pladevalueinpts of <DIMENSION REGISTER> in {CONTROL SEQUENCE}
  362. \def\placevalueinpts of <#1> in #2 {%
  363.   \!removept{#1}{#2}}
  364. % ** \!mlap{...}  \!vmlap{...}
  365. % ** Center  ...  in a box of width 0.
  366. \def\!mlap#1{\hbox to 0pt{\hss#1\hss}}
  367. \def\!vmlap#1{\vbox to 0pt{\vss#1\vss}}
  368. % ** \!not{TEK if-CONDITION}
  369. % ** By a TEK if-CONDITION is meant something like 
  370. % **     \ifnum\N<0,   or   \ifdim\A>\B
  371. % ** \!not produces an if-condition which is false if the original condition
  372. % ** is true, and true if the original condition is false.
  373. \def\!not#1{%
  374.   #1\relax
  375.     \!switchfalse
  376.   \else
  377.     \!switchtrue
  378.   \fi
  379.   \if!switch
  380.   \ignorespaces}
  381. % *******************
  382. % *** ALLOCATIONS ***
  383. % *******************
  384. % This section allocates all the registers PiCTeX uses. Following
  385. % each allocation is a string of the form  ....N.D...L......... ;
  386. % the various letters show which sections of PiCTeX make explicit
  387. % reference to that register, according to the following code:
  388. %   H Hacks
  389. %   A Areas
  390. %   W arroWs
  391. %   B Bars
  392. %   X boXes
  393. %   C Curves
  394. %   D Dashpattterns
  395. %   V diVision
  396. %   E Ellipses
  397. %   U rUles
  398. %   L Linear arc
  399. %   G loGten
  400. %   P Pictures
  401. %   O plOtting
  402. %   Y pYthagoras
  403. %   Q Quadratic arc
  404. %   R Rotations
  405. %   S Shading
  406. %   T Ticks
  407. % Turn off messages from TeX's allocation macros
  408. \let\!!!wlog=\wlog              % "\wlog" is defined in plain TeX
  409. \def\wlog#1{}    
  410. \newdimen\headingtoplotskip     %.A.................
  411. \newdimen\linethickness         %.A..X....U........T
  412. \newdimen\longticklength        %.A................T
  413. \newdimen\plotsymbolspacing     %......D...L....Q...
  414. \newdimen\shortticklength       %.A................T
  415. \newdimen\stackleading          %.A..........P......
  416. \newdimen\tickstovaluesleading  %.A................T
  417. \newdimen\totalarclength        %......D...L....Q...
  418. \newdimen\valuestolabelleading  %.A.................
  419. \newbox\!boxA                   %.AW...............T
  420. \newbox\!boxB                   %..W................
  421. \newbox\!picbox                 %............P......
  422. \newbox\!plotsymbol             %..........L..O.....
  423. \newbox\!putobject              %............PO...S.
  424. \newbox\!shadesymbol            %.................S.
  425. \newcount\!countA               %.A....D..UL....Q.ST
  426. \newcount\!countB               %......D..U.....Q.ST
  427. \newcount\!countC               %...............Q..T
  428. \newcount\!countD               %...................
  429. \newcount\!countE               %.............O....T
  430. \newcount\!countF               %.............O....T
  431. \newcount\!countG               %..................T
  432. \newcount\!fiftypt              %.........U.........
  433. \newcount\!intervalno           %..........L....Q...
  434. \newcount\!npoints              %..........L........
  435. \newcount\!nsegments            %.........U.........
  436. \newcount\!ntemp                %............P......
  437. \newcount\!parity               %.................S.
  438. \newcount\!scalefactor          %..................T
  439. \newcount\!tfs                  %.......V...........
  440. \newcount\!tickcase             %..................T
  441. \newdimen\!Xleft                %............P......
  442. \newdimen\!Xright               %............P......
  443. \newdimen\!Xsave                %.A................T
  444. \newdimen\!Ybot                 %............P......
  445. \newdimen\!Ysave                %.A................T
  446. \newdimen\!Ytop                 %............P......
  447. \newdimen\!angle                %........E..........
  448. \newdimen\!arclength            %..W......UL....Q...
  449. \newdimen\!areabloc             %.A........L........
  450. \newdimen\!arealloc             %.A........L........
  451. \newdimen\!arearloc             %.A........L........
  452. \newdimen\!areatloc             %.A........L........
  453. \newdimen\!bshrinkage           %.................S.
  454. \newdimen\!checkbot             %..........L........
  455. \newdimen\!checkleft            %..........L........
  456. \newdimen\!checkright           %..........L........
  457. \newdimen\!checktop             %..........L........
  458. \newdimen\!dimenA               %.AW.X.DVEUL..OYQRST
  459. \newdimen\!dimenB               %....X.DVEU...O.QRS.
  460. \newdimen\!dimenC               %..W.X.DVEU......RS.
  461. \newdimen\!dimenD               %..W.X.DVEU....Y.RS.
  462. \newdimen\!dimenE               %..W........G..YQ.S.
  463. \newdimen\!dimenF               %...........G..YQ.S.
  464. \newdimen\!dimenG               %...........G..YQ.S.
  465. \newdimen\!dimenH               %...........G..Y..S.
  466. \newdimen\!dimenI               %...BX.........Y....
  467. \newdimen\!distacross           %..........L....Q...
  468. \newdimen\!downlength           %..........L........
  469. \newdimen\!dp                   %.A..X.......P....S.
  470. \newdimen\!dshade               %.................S.
  471. \newdimen\!dxpos                %..W......U..P....S.
  472. \newdimen\!dxprime              %...............Q...
  473. \newdimen\!dypos                %..WB.....U..P......
  474. \newdimen\!dyprime              %...............Q...
  475. \newdimen\!ht                   %.A..X.......P....S.
  476. \newdimen\!leaderlength         %......D..U.........
  477. \newdimen\!lshrinkage           %.................S.
  478. \newdimen\!midarclength         %...............Q...
  479. \newdimen\!offset               %.A................T
  480. \newdimen\!plotheadingoffset    %.A.................
  481. \newdimen\!plotsymbolxshift     %..........L..O.....
  482. \newdimen\!plotsymbolyshift     %..........L..O.....
  483. \newdimen\!plotxorigin          %..........L..O.....
  484. \newdimen\!plotyorigin          %..........L..O.....
  485. \newdimen\!rootten              %...........G.......
  486. \newdimen\!rshrinkage           %.................S.
  487. \newdimen\!shadesymbolxshift    %.................S.
  488. \newdimen\!shadesymbolyshift    %.................S.
  489. \newdimen\!tenAa                %...........G.......
  490. \newdimen\!tenAc                %...........G.......
  491. \newdimen\!tenAe                %...........G.......
  492. \newdimen\!tshrinkage           %.................S.
  493. \newdimen\!uplength             %..........L........
  494. \newdimen\!wd                   %....X.......P....S.
  495. \newdimen\!wmax                 %...............Q...
  496. \newdimen\!wmin                 %...............Q...
  497. \newdimen\!xB                   %...............Q...
  498. \newdimen\!xC                   %...............Q...
  499. \newdimen\!xE                   %..W.....E.L....Q.S.
  500. \newdimen\!xM                   %..W.....E......Q.S.
  501. \newdimen\!xS                   %..W.....E.L....Q.S.
  502. \newdimen\!xaxislength          %.A................T
  503. \newdimen\!xdiff                %..........L........
  504. \newdimen\!xleft                %............P......
  505. \newdimen\!xloc                 %..WB.....U.......S.
  506. \newdimen\!xorigin              %.A........L.P....S.
  507. \newdimen\!xpivot               %................R..
  508. \newdimen\!xpos                 %..........L.P..Q.ST
  509. \newdimen\!xprime               %...............Q...
  510. \newdimen\!xright               %............P......
  511. \newdimen\!xshade               %.................S.
  512. \newdimen\!xshift               %..W.........PO...S.
  513. \newdimen\!xtemp                %............P......
  514. \newdimen\!xunit                %.AWBX...EUL.P..QRS.
  515. \newdimen\!xxE                  %........E..........
  516. \newdimen\!xxM                  %........E..........
  517. \newdimen\!xxS                  %........E..........
  518. \newdimen\!xxloc                %..WB....EU.........
  519. \newdimen\!yB                   %...............Q...
  520. \newdimen\!yC                   %...............Q...
  521. \newdimen\!yE                   %..W.....E.L....Q...
  522. \newdimen\!yM                   %..W.....E......Q...
  523. \newdimen\!yS                   %..W.....E.L....Q...
  524. \newdimen\!yaxislength          %.A................T
  525. \newdimen\!ybot                 %............P......
  526. \newdimen\!ydiff                %..........L........
  527. \newdimen\!yloc                 %..WB.....U.......S.
  528. \newdimen\!yorigin              %.A........L.P....S.
  529. \newdimen\!ypivot               %................R..
  530. \newdimen\!ypos                 %..........L.P..Q.ST
  531. \newdimen\!yprime               %...............Q...
  532. \newdimen\!yshade               %.................S.
  533. \newdimen\!yshift               %..W.........PO...S.
  534. \newdimen\!ytemp                %............P......
  535. \newdimen\!ytop                 %............P......
  536. \newdimen\!yunit                %.AWBX...EUL.P..QRS.
  537. \newdimen\!yyE                  %........E..........
  538. \newdimen\!yyM                  %........E..........
  539. \newdimen\!yyS                  %........E..........
  540. \newdimen\!yyloc                %..WB....EU.........
  541. \newdimen\!zpt                  %.AWBX.DVEULGP.YQ.ST
  542. \newif\if!axisvisible           %.A.................
  543. \newif\if!gridlinestoo          %..................T
  544. \newif\if!keepPO                %...................
  545. \newif\if!placeaxislabel        %.A.................
  546. \newif\if!switch                %H..................
  547. \newif\if!xswitch               %.A................T
  548. \newtoks\!axisLaBeL             %.A.................
  549. \newtoks\!keywordtoks           %.A.................
  550. \newwrite\!replotfile           %.............O.....
  551. \newhelp\!keywordhelp{The keyword mentioned in the error message in unknown. 
  552. Replace NEW KEYWORD in the indicated response by the keyword that 
  553. should have been specified.}    %.A.................
  554. % The following commands assign alternate names to some of the 
  555. % above registers.  "\!wlet"  is defined in  Hacks.
  556. \!wlet\!!origin=\!xM                   %.A................T
  557. \!wlet\!!unit=\!uplength               %.A................T
  558. \!wlet\!Lresiduallength=\!dimenG       %.........U.........
  559. \!wlet\!Rresiduallength=\!dimenF       %.........U.........
  560. \!wlet\!axisLength=\!distacross        %.A................T
  561. \!wlet\!axisend=\!ydiff                %.A................T
  562. \!wlet\!axisstart=\!xdiff              %.A................T
  563. \!wlet\!axisxlevel=\!arclength         %.A................T
  564. \!wlet\!axisylevel=\!downlength        %.A................T
  565. \!wlet\!beta=\!dimenE                  %...............Q...
  566. \!wlet\!gamma=\!dimenF                 %...............Q...
  567. \!wlet\!shadexorigin=\!plotxorigin     %.................S.
  568. \!wlet\!shadeyorigin=\!plotyorigin     %.................S.
  569. \!wlet\!ticklength=\!xS                %..................T
  570. \!wlet\!ticklocation=\!xE              %..................T
  571. \!wlet\!ticklocationincr=\!yE          %..................T
  572. \!wlet\!tickwidth=\!yS                 %..................T
  573. \!wlet\!totalleaderlength=\!dimenE     %.........U.........
  574. \!wlet\!xone=\!xprime                  %....X..............
  575. \!wlet\!xtwo=\!dxprime                 %....X..............
  576. \!wlet\!ySsave=\!yM                    %...................
  577. \!wlet\!ybB=\!yB                       %.................S.
  578. \!wlet\!ybC=\!yC                       %.................S.
  579. \!wlet\!ybE=\!yE                       %.................S.
  580. \!wlet\!ybM=\!yM                       %.................S.
  581. \!wlet\!ybS=\!yS                       %.................S.
  582. \!wlet\!ybpos=\!yyloc                  %.................S.
  583. \!wlet\!yone=\!yprime                  %....X..............
  584. \!wlet\!ytB=\!xB                       %.................S.
  585. \!wlet\!ytC=\!xC                       %.................S.
  586. \!wlet\!ytE=\!downlength               %.................S.
  587. \!wlet\!ytM=\!arclength                %.................S.
  588. \!wlet\!ytS=\!distacross               %.................S.
  589. \!wlet\!ytpos=\!xxloc                  %.................S.
  590. \!wlet\!ytwo=\!dyprime                 %....X..............
  591. % Initial values for registers
  592. \!zpt=0pt                              % static
  593. \!xunit=1pt
  594. \!yunit=1pt
  595. \!arearloc=\!xunit
  596. \!areatloc=\!yunit
  597. \!dshade=5pt
  598. \!leaderlength=24in
  599. \!tfs=256                              % static
  600. \!wmax=5.3pt                           % static
  601. \!wmin=2.7pt                           % static
  602. \!xaxislength=\!xunit
  603. \!xpivot=\!zpt
  604. \!yaxislength=\!yunit 
  605. \!ypivot=\!zpt
  606. \plotsymbolspacing=.4pt
  607.   \!dimenA=50pt \!fiftypt=\!dimenA     % static
  608. \!rootten=3.162278pt                   % static
  609. \!tenAa=8.690286pt                     % static  (A5)
  610. \!tenAc=2.773839pt                     % static  (A3)
  611. \!tenAe=2.543275pt                     % static  (A1)
  612. % Initial values for control sequences
  613. \def\!cosrotationangle{1}      %................R..
  614. \def\!sinrotationangle{0}      %................R..
  615. \def\!xpivotcoord{0}           %................R..
  616. \def\!xref{0}                  %............P......
  617. \def\!xshadesave{0}            %.................S.
  618. \def\!ypivotcoord{0}           %................R..
  619. \def\!yref{0}                  %............P......
  620. \def\!yshadesave{0}            %.................S.
  621. \def\!zero{0}                  %..................T
  622. % Reset TeX to report allocations
  623. \let\wlog=\!!!wlog
  624. %  *************************************
  625. %  ***  AREAS: Deals with plot areas ***
  626. %  *************************************
  627. %  ** User commands
  628. %  **   \setplotarea x from LEFT XCOORD to RIGTH XCOORD, y from BOTTOM YCOORD
  629. %  **      to TOP YCOORD
  630. %  **   \axis BOTTOM-LEFT-TOP-RIGHT  [SHIFTEDTO xy=COORD] [VISIBLE-INVISIBLE]
  631. %  **      [LABEL {label}] [TICKS] /
  632. %  **   \visibleaxes
  633. %  **   \invisibleaxes
  634. %  **   \plotheading {HEADING}
  635. %  **   \grid {# of columns} {# of rows}
  636. %  **   \normalgraphs 
  637. %  **  \normalgraphs
  638. %  **    Sets defaults for graph setup. See Subsection 3.4 of manual.
  639. \def\normalgraphs{%
  640.   \longticklength=.4\baselineskip
  641.   \shortticklength=.25\baselineskip
  642.   \tickstovaluesleading=.25\baselineskip
  643.   \valuestolabelleading=.8\baselineskip
  644.   \linethickness=.4pt
  645.   \stackleading=.17\baselineskip
  646.   \headingtoplotskip=1.5\baselineskip
  647.   \visibleaxes
  648.   \ticksout
  649.   \nogridlines
  650.   \unloggedticks}
  651. % **  \setplotarea x from LEFT XCOORD to RIGTH XCOORD, y from BOTTOM YCOORD
  652. % **    to TOP YCOORD
  653. % **  Reserves space in PICBOX for a rectangular box with the indicated
  654. % **   coordinates.  Must be specified before calls to  \axis, 
  655. % **   \grid, \plotheading.
  656. % **  See Subsection 3.1 of the manual.
  657. \def\setplotarea x from #1 to #2, y from #3 to #4 {%
  658.   \!arealloc=\!M{#1}\!xunit \advance \!arealloc -\!xorigin
  659.   \!areabloc=\!M{#3}\!yunit \advance \!areabloc -\!yorigin
  660.   \!arearloc=\!M{#2}\!xunit \advance \!arearloc -\!xorigin
  661.   \!areatloc=\!M{#4}\!yunit \advance \!areatloc -\!yorigin
  662.   \!initinboundscheck
  663.   \!xaxislength=\!arearloc  \advance\!xaxislength -\!arealloc
  664.   \!yaxislength=\!areatloc  \advance\!yaxislength -\!areabloc
  665.   \!plotheadingoffset=\!zpt
  666.   \!dimenput {{\setbox0=\hbox{}\wd0=\!xaxislength\ht0=\!yaxislength\box0}}
  667.      [bl] (\!arealloc,\!areabloc)}
  668. % ** \visibleaxes, \invisibleaxes 
  669. % ** Switches for setting visibility of subsequent axes.
  670. % ** See Subsection 3.2 of the manual.
  671. \def\visibleaxes{%
  672.   \def\!axisvisibility{\!axisvisibletrue}}
  673. \def\invisibleaxes{%
  674.   \def\!axisvisibility{\!axisvisiblefalse}}
  675. % ** The next few macros enable the user to fix up an erroneous keyword
  676. % **   in the \axis command.
  677. %  \newhelp is in ALLOCATIONS
  678. %  \newhelp\!keywordhelp{The keyword mentioned in the error message in unknown. 
  679. %  Replace NEW KEYWORD in the indicated response by the keyword that 
  680. %  should have been specified.}
  681. \def\!fixkeyword#1{%
  682.   \errhelp=\!keywordhelp
  683.   \errmessage{Unrecognized keyword `#1': \the\!keywordtoks{NEW KEYWORD}'}}
  684. %  \newtoks\!keywordtoks    In ALLOCATIONS.
  685. \!keywordtoks={enter `i\fixkeyword}
  686. \def\fixkeyword#1{%
  687.   \!nextkeyword#1 }
  688. % ** \axis BOTTOM-LEFT-TOP-RIGHT  [SHIFTEDTO xy=COORD] [VISIBLE-INVISIBLE]
  689. % **   [LABEL {label}] [TICKS] /
  690. % ** Exactly one of the keywords BOTTOM, LEFT, TOP, RIGHT must be
  691. % ** specified. Axis is drawn along the indicated edge of the current
  692. % ** plot area, shifted if the SHIFTEDTO option is used, visible or
  693. % ** invisible according the selected option, with an optional LABEL,
  694. % ** and optional TICKS (see ticks.tex for the options avialabel with
  695. % ** TICKS). The TICKS option must be the last one specified. The \axis
  696. % ** MUST be terminated with a / followed by a space.
  697. % ** See Subsection 3.2 of the manual for more information.
  698. % ** The various options of the \axis command are processed by the
  699. % ** \!nextkeyword macro defined below. For example, 
  700. % ** `\!nextkeyword shiftedto ' expands to `\!axisshiftedto'.
  701. \def\axis {%
  702.   \def\!nextkeyword##1 {%
  703.     \expandafter\ifx\csname !axis##1\endcsname \relax
  704.       \def\!next{\!fixkeyword{##1}}%
  705.     \else
  706.       \def\!next{\csname !axis##1\endcsname}%
  707.     \fi
  708.     \!next}%
  709.   \!offset=\!zpt
  710.   \!axisvisibility
  711.   \!placeaxislabelfalse
  712.   \!nextkeyword}
  713. % ** This and the various macros that follow handle the keyword
  714. % ** specifications on the \axis command
  715. % ** See Subsection 3.2 of the manual.
  716. \def\!axisbottom{%
  717.   \!axisylevel=\!areabloc
  718.   \def\!tickxsign{0}%
  719.   \def\!tickysign{-}%
  720.   \def\!axissetup{\!axisxsetup}%
  721.   \def\!axislabeltbrl{t}%
  722.   \!nextkeyword}
  723. \def\!axistop{%
  724.   \!axisylevel=\!areatloc
  725.   \def\!tickxsign{0}%
  726.   \def\!tickysign{+}%
  727.   \def\!axissetup{\!axisxsetup}%
  728.   \def\!axislabeltbrl{b}%
  729.   \!nextkeyword}
  730. \def\!axisleft{%
  731.   \!axisxlevel=\!arealloc
  732.   \def\!tickxsign{-}%
  733.   \def\!tickysign{0}%
  734.   \def\!axissetup{\!axisysetup}%
  735.   \def\!axislabeltbrl{r}%
  736.   \!nextkeyword}
  737. \def\!axisright{%
  738.   \!axisxlevel=\!arearloc
  739.   \def\!tickxsign{+}%
  740.   \def\!tickysign{0}%
  741.   \def\!axissetup{\!axisysetup}%
  742.   \def\!axislabeltbrl{l}%
  743.   \!nextkeyword}
  744. \def\!axisshiftedto#1=#2 {%
  745.   \if 0\!tickxsign
  746.     \!axisylevel=\!M{#2}\!yunit
  747.     \advance\!axisylevel -\!yorigin
  748.   \else
  749.     \!axisxlevel=\!M{#2}\!xunit
  750.     \advance\!axisxlevel -\!xorigin
  751.   \fi
  752.   \!nextkeyword}
  753. \def\!axisvisible{%
  754.   \!axisvisibletrue  
  755.   \!nextkeyword}
  756. \def\!axisinvisible{%
  757.   \!axisvisiblefalse
  758.   \!nextkeyword}
  759. \def\!axislabel#1 {%
  760.   \!axisLaBeL={#1}%
  761.   \!placeaxislabeltrue
  762.   \!nextkeyword}
  763. \expandafter\def\csname !axis/\endcsname{%
  764.   \!axissetup % This could done already by "ticks"; if so, now \relax
  765.   \if!placeaxislabel
  766.     \!placeaxislabel
  767.   \fi
  768.   \if +\!tickysign %                 ** (A "top" axis)
  769.     \!dimenA=\!axisylevel
  770.     \advance\!dimenA \!offset %      ** dimA = top of the axis structure
  771.     \advance\!dimenA -\!areatloc %   ** dimA = excess over the plot area
  772.     \ifdim \!dimenA>\!plotheadingoffset
  773.       \!plotheadingoffset=\!dimenA % ** Greatest excess over the plot area
  774.     \fi
  775.   \fi}
  776. % ** \grid {c} {r} 
  777. % ** Partitions the plot area into c columns and r rows; see Subsection 3.3
  778. % ** of the manual.
  779. % ** (Other grid patterns can be drawn with the TICKS option of the \axis 
  780. % ** command.
  781. \def\grid #1 #2 {%
  782.   \!countA=#1\advance\!countA 1
  783.   \axis bottom invisible ticks length <\!zpt> andacross quantity {\!countA} /
  784.   \!countA=#2\advance\!countA 1
  785.   \axis left   invisible ticks length <\!zpt> andacross quantity {\!countA} / }
  786. % ** \plotheading{HEADING}
  787. % ** Places HEADING centered above the top of the plotarea (and above
  788. % ** any top axis ticks marks, tick labels, and axis label); see
  789. % ** Subsection 3.3 of the manual.
  790. \def\plotheading#1 {%
  791.   \advance\!plotheadingoffset \headingtoplotskip
  792.   \!dimenput {#1} [B] <.5\!xaxislength,\!plotheadingoffset>
  793.     (\!arealloc,\!areatloc)}
  794. % ** From here on, the routines are internal.
  795. \def\!axisxsetup{%
  796.   \!axisxlevel=\!arealloc
  797.   \!axisstart=\!arealloc
  798.   \!axisend=\!arearloc
  799.   \!axisLength=\!xaxislength
  800.   \!!origin=\!xorigin
  801.   \!!unit=\!xunit
  802.   \!xswitchtrue
  803.   \if!axisvisible 
  804.     \!makeaxis
  805.   \fi}
  806. \def\!axisysetup{%
  807.   \!axisylevel=\!areabloc
  808.   \!axisstart=\!areabloc
  809.   \!axisend=\!areatloc
  810.   \!axisLength=\!yaxislength
  811.   \!!origin=\!yorigin
  812.   \!!unit=\!yunit
  813.   \!xswitchfalse
  814.   \if!axisvisible
  815.     \!makeaxis
  816.   \fi}
  817. \def\!makeaxis{%
  818.   \setbox\!boxA=\hbox{% (Make a pseudo-y[x] tick for an x[y]-axis)
  819.     \beginpicture
  820.       \!setdimenmode
  821.       \setcoordinatesystem point at {\!zpt} {\!zpt}   
  822.       \putrule from {\!zpt} {\!zpt} to
  823.         {\!tickysign\!tickysign\!axisLength} 
  824.         {\!tickxsign\!tickxsign\!axisLength}
  825.     \endpicturesave <\!Xsave,\!Ysave>}%
  826.     \wd\!boxA=\!zpt
  827.     \!placetick\!axisstart}
  828. \def\!placeaxislabel{%
  829.   \advance\!offset \valuestolabelleading
  830.   \if!xswitch
  831.     \!dimenput {\the\!axisLaBeL} [\!axislabeltbrl]
  832.       <.5\!axisLength,\!tickysign\!offset> (\!axisxlevel,\!axisylevel)
  833.     \advance\!offset \!dp  % ** advance offset by the "tallness"
  834.     \advance\!offset \!ht  % ** of the label
  835.   \else
  836.     \!dimenput {\the\!axisLaBeL} [\!axislabeltbrl]
  837.       <\!tickxsign\!offset,.5\!axisLength> (\!axisxlevel,\!axisylevel)
  838.   \fi
  839.   \!axisLaBeL={}}
  840. % *******************************
  841. % *** ARROWS  (Draws arrows)  ***
  842. % *******************************
  843. % ** User commands
  844. % **  \arrow <ARROW HEAD LENGTH> [MID FRACTION, BASE FRACTION]
  845. % **    [<XSHIFT,YSHIFT>] from XFROM YFROM to XTO YTO
  846. % **  \betweenarrows {TEXT} [orientation & shift] from XFROM YFROM to XTO YTO
  847. % ** \arrow <ARROW HEAD LENGTH> [MID FRACTION, BASE FRACTION]
  848. % **    [<XSHIFT,YSHIFT>] from XFROM YFROM to XTO YTO
  849. % ** Draws an arrow from (XFROM,YFROM) to (XTO,YTO).  The arrow head
  850. % ** is constructed two quadratic arcs, which extend back a distance
  851. % ** ARROW HEAD LENGTH (a dimension) on both sides of the arrow shaft.
  852. % ** All the way back the arcs are a distance BASE FRACTION*ARROW HEAD
  853. % ** LENGTH apart, while half-way back they are a distance MID FRACTION*
  854. % ** ARROW HEAD LENGTH apart. <XSHIFT,YSHIFT> is optional, and has
  855. % ** its usual interpreation. See Subsection 5.4 of the manual.
  856. \def\arrow <#1> [#2,#3]{%
  857.   \!ifnextchar<{\!arrow{#1}{#2}{#3}}{\!arrow{#1}{#2}{#3}<\!zpt,\!zpt> }}
  858. \def\!arrow#1#2#3<#4,#5> from #6 #7 to #8 #9 {%
  859. % ** convert to dimensions
  860.   \!xloc=\!M{#8}\!xunit   
  861.   \!yloc=\!M{#9}\!yunit
  862.   \!dxpos=\!xloc  \!dimenA=\!M{#6}\!xunit  \advance \!dxpos -\!dimenA
  863.   \!dypos=\!yloc  \!dimenA=\!M{#7}\!yunit  \advance \!dypos -\!dimenA
  864.   \let\!MAH=\!M%                         ** save current c/d mode
  865.   \!setdimenmode%                        ** go into dimension mode
  866.   \!xshift=#4\relax  \!yshift=#5\relax%  ** pick up shift
  867.   \!reverserotateonly\!xshift\!yshift%   ** back rotate shift
  868.   \advance\!xshift\!xloc  \advance\!yshift\!yloc
  869. % **  draw shaft of arrow
  870.   \!xS=-\!dxpos  \advance\!xS\!xshift
  871.   \!yS=-\!dypos  \advance\!yS\!yshift
  872.   \!start (\!xS,\!yS)
  873.   \!ljoin (\!xshift,\!yshift)
  874. % ** find 32*cosine and 32*sine of angle of rotation
  875.   \!Pythag\!dxpos\!dypos\!arclength
  876.   \!divide\!dxpos\!arclength\!dxpos  
  877.   \!dxpos=32\!dxpos  \!removept\!dxpos\!!cos
  878.   \!divide\!dypos\!arclength\!dypos  
  879.   \!dypos=32\!dypos  \!removept\!dypos\!!sin
  880. % ** construct arrowhead
  881.   \!halfhead{#1}{#2}{#3}%                ** draw half of arrow head
  882.   \!halfhead{#1}{-#2}{-#3}%              ** draw other half
  883.   \let\!M=\!MAH%                         ** restore old c/d mode
  884.   \ignorespaces}
  885. % ** draw half of arrow head
  886.   \def\!halfhead#1#2#3{%
  887.     \!dimenC=-#1%                
  888.     \divide \!dimenC 2 %                 ** half way back
  889.     \!dimenD=#2\!dimenC%                 ** half the mid width
  890.     \!rotate(\!dimenC,\!dimenD)by(\!!cos,\!!sin)to(\!xM,\!yM)
  891.     \!dimenC=-#1%                        ** all the way back
  892.     \!dimenD=#3\!dimenC
  893.     \!dimenD=.5\!dimenD%                 ** half the full width
  894.     \!rotate(\!dimenC,\!dimenD)by(\!!cos,\!!sin)to(\!xE,\!yE)
  895.     \!start (\!xshift,\!yshift)
  896.     \advance\!xM\!xshift  \advance\!yM\!yshift
  897.     \advance\!xE\!xshift  \advance\!yE\!yshift
  898.     \!qjoin (\!xM,\!yM) (\!xE,\!yE) 
  899.     \ignorespaces}
  900. % ** \betweenarrows {TEXT} [orientation & shift] from XFROM YFROM to XTO YTO
  901. % **   Makes things like <--- text --->, using arrow heads from TeX's fonts.
  902. % **   See Subsection 5.4 of the manual.
  903. \def\betweenarrows #1#2 from #3 #4 to #5 #6 {%
  904.   \!xloc=\!M{#3}\!xunit  \!xxloc=\!M{#5}\!xunit%   
  905.   \!yloc=\!M{#4}\!yunit  \!yyloc=\!M{#6}\!yunit%           
  906.   \!dxpos=\!xxloc  \advance\!dxpos by -\!xloc
  907.   \!dypos=\!yyloc  \advance\!dypos by -\!yloc
  908.   \advance\!xloc .5\!dxpos
  909.   \advance\!yloc .5\!dypos
  910.   \let\!MBA=\!M%           ** save current coord\dimen mode
  911.   \!setdimenmode%          ** express locations in dimens
  912.   \ifdim\!dypos=\!zpt
  913.     \ifdim\!dxpos<\!zpt \!dxpos=-\!dxpos \fi
  914.     \put {\!lrarrows{\!dxpos}{#1}}#2{} at {\!xloc} {\!yloc}
  915.   \else
  916.     \ifdim\!dxpos=\!zpt
  917.       \ifdim\!dypos<\!zpt \!dypos=-\!zpt \fi
  918.       \put {\!udarrows{\!dypos}{#1}}#2{} at {\!xloc} {\!yloc}
  919.     \fi
  920.   \fi
  921.   \let\!M=\!MBA%           ** restore previous c/d mode
  922.   \ignorespaces}
  923. % ** Subroutine for left-right between arrows 
  924. \def\!lrarrows#1#2{% #1=width, #2=text
  925.   {\setbox\!boxA=\hbox{$\mkern-2mu\mathord-\mkern-2mu$}%
  926.    \setbox\!boxB=\hbox{$\leftarrow$}\!dimenE=\ht\!boxB
  927.    \setbox\!boxB=\hbox{}\ht\!boxB=2\!dimenE
  928.    \hbox to #1{$\mathord\leftarrow\mkern-6mu
  929.      \cleaders\copy\!boxA\hfil
  930.      \mkern-6mu\mathord-$%
  931.      \kern.4em $\vcenter{\box\!boxB}$$\vcenter{\hbox{#2}}$\kern.4em
  932.      $\mathord-\mkern-6mu
  933.      \cleaders\copy\!boxA\hfil
  934.      \mkern-6mu\mathord\rightarrow$}}}
  935. % ** Subroutine for up-down between arrows 
  936. \def\!udarrows#1#2{% #1=width, #2=text
  937.   {\setbox\!boxB=\hbox{#2}%
  938.    \setbox\!boxA=\hbox to \wd\!boxB{\hss$\vert$\hss}%
  939.    \!dimenE=\ht\!boxA \advance\!dimenE \dp\!boxA \divide\!dimenE 2
  940.    \vbox to #1{\offinterlineskip
  941.       \vskip .05556\!dimenE
  942.       \hbox to \wd\!boxB{\hss$\mkern.4mu\uparrow$\hss}\vskip-\!dimenE
  943.       \cleaders\copy\!boxA\vfil
  944.       \vskip-\!dimenE\copy\!boxA
  945.       \vskip\!dimenE\copy\!boxB\vskip.4em
  946.       \copy\!boxA\vskip-\!dimenE
  947.       \cleaders\copy\!boxA\vfil
  948.       \vskip-\!dimenE \hbox to \wd\!boxB{\hss$\mkern.4mu\downarrow$\hss}
  949.       \vskip .05556\!dimenE}}}
  950. % ***************************
  951. % *** BARS  (Draws bars)  ***
  952. % ***************************
  953. % ** User commands:
  954. % ** \putbar [<XSHIFT,YSHIFT>] breadth <BREADTH> from XSTART YSTART
  955. % **   to XEND YEND
  956. % ** \setbars [<XSHIFT,YSHIFT>] breadth <BREADTH> baseline at XY = COORD
  957. % **   [baselabels ([B_ORIENTATION_x,B_ORIENTATION_y] <B_XSHIFT,B_YSHIFT>)]
  958. % **   [endlabels  ([E_ORIENTATION_x,E_ORIENTATION_y] <E_XSHIFT,E_YSHIFT>)]
  959. % ** \putbar [<XSHIFT,YSHIFT>] breadth <BREADTH> from XSTART YSTART
  960. % **   to XEND YEND
  961. % ** Either XSTART=XEND or YSTART=YEND. Draws a rectangle between
  962. % **   (XSTART,YSTART) & (XEND,YEND). The "depth" of the rectangle
  963. % **   is determined by those two plot positions; its other
  964. % **   dimension "breadth" is specified by the dimension BREADTH.
  965. % ** See Subsection 4.2 of the manual.
  966. \def\putbar#1breadth <#2> from #3 #4 to #5 #6 {%
  967.   \!xloc=\!M{#3}\!xunit  \!xxloc=\!M{#5}\!xunit%   
  968.   \!yloc=\!M{#4}\!yunit  \!yyloc=\!M{#6}\!yunit%           
  969.   \!dypos=\!yyloc  \advance\!dypos by -\!yloc
  970.   \!dimenI=#2  
  971.   \ifdim \!dimenI=\!zpt %            ** If 0 breadth
  972.     \putrule#1from {#3} {#4} to {#5} {#6} % ** Then draw line
  973.   \else %                            ** Else, put in a rectangle
  974.     \let\!MBar=\!M%                  ** save current c/d mode
  975.     \!setdimenmode %                 ** go into dimension mode
  976.     \divide\!dimenI 2
  977.     \ifdim \!dypos=\!zpt             
  978.       \advance \!yloc -\!dimenI %    ** Equal y coordinates
  979.       \advance \!yyloc \!dimenI
  980.     \else
  981.       \advance \!xloc -\!dimenI %    ** Equal x coordinates
  982.       \advance \!xxloc \!dimenI
  983.     \fi
  984.     \putrectangle#1corners at {\!xloc} {\!yloc} and {\!xxloc} {\!yyloc}
  985.     \let\!M=\!MBar %                 ** restore c/d mode
  986.   \fi
  987.   \ignorespaces}
  988. % ** \setbars [<XSHIFT,YSHIFT>] breadth <BREADTH> baseline at XY = COORD
  989. % **   [baselabels ([B_ORIENTATION_x,B_ORIENTATION_y] <B_XSHIFT,B_YSHIFT>)]
  990. % **   [endlabels  ([E_ORIENTATION_x,E_ORIENTATION_y] <E_XSHIFT,E_YSHIFT>)]
  991. % ** This command puts PiCTeX into the bar graph drawing mode described
  992. % **   in Subsection 4.4 of the manual.
  993. \def\setbars#1breadth <#2> baseline at #3 = #4 {%
  994.   \edef\!barshift{#1}%
  995.   \edef\!barbreadth{#2}%
  996.   \edef\!barorientation{#3}%
  997.   \edef\!barbaseline{#4}%
  998.   \def\!bardobaselabel{\!bardoendlabel}%
  999.   \def\!bardoendlabel{\!barfinish}%
  1000.   \let\!drawcurve=\!barcurve
  1001.   \!setbars}
  1002. \def\!setbars{%
  1003.   \futurelet\!nextchar\!!setbars}
  1004. \def\!!setbars{%
  1005.   \if b\!nextchar
  1006.     \def\!!!setbars{\!setbarsbget}%
  1007.   \else 
  1008.     \if e\!nextchar
  1009.       \def\!!!setbars{\!setbarseget}%
  1010.     \else
  1011.       \def\!!!setbars{\relax}%
  1012.     \fi
  1013.   \fi
  1014.   \!!!setbars}
  1015. \def\!setbarsbget baselabels (#1) {%
  1016.   \def\!barbaselabelorientation{#1}%
  1017.   \def\!bardobaselabel{\!!bardobaselabel}%
  1018.   \!setbars}
  1019. \def\!setbarseget endlabels (#1) {%
  1020.   \edef\!barendlabelorientation{#1}%
  1021.   \def\!bardoendlabel{\!!bardoendlabel}%
  1022.   \!setbars}
  1023. % ** \!barcurve
  1024. % ** Draws a bargraph with preset values of barshift, barbreadth,
  1025. % ** barorientation (x or y) and barbaseline (coordinate)
  1026. \def\!barcurve #1 #2 {%
  1027.   \if y\!barorientation
  1028.     \def\!basexarg{#1}%
  1029.     \def\!baseyarg{\!barbaseline}%
  1030.   \else
  1031.     \def\!basexarg{\!barbaseline}%
  1032.     \def\!baseyarg{#2}%
  1033.   \fi
  1034.   \expandafter\putbar\!barshift breadth <\!barbreadth> from {\!basexarg}
  1035.     {\!baseyarg} to {#1} {#2}
  1036.   \def\!endxarg{#1}%
  1037.   \def\!endyarg{#2}%
  1038.   \!bardobaselabel}
  1039. \def\!!bardobaselabel "#1" {%
  1040.   \put {#1}\!barbaselabelorientation{} at {\!basexarg} {\!baseyarg}
  1041.   \!bardoendlabel}
  1042. \def\!!bardoendlabel "#1" {%
  1043.   \put {#1}\!barendlabelorientation{} at {\!endxarg} {\!endyarg}
  1044.   \!barfinish}
  1045. \def\!barfinish{%
  1046.   \!ifnextchar/{\!finish}{\!barcurve}}
  1047. % ********************************
  1048. % *** BOXES (Draws rectangles) ***
  1049. % ********************************
  1050. % ** User commands:
  1051. % **   \putrectangle [<XSHIFT,YSHIFT>] corners at  XCOORD1 YCOORD1
  1052. % **     and  XCOORD2 YCOORD2 
  1053. % **   \shaderectangleson
  1054. % **   \shaderectanglesoff
  1055. % **   \frame [<SEPARATION>] {TEXT}
  1056. % **   \rectangle <WIDTH> <HEIGHT>
  1057. % **  \putrectangle [<XSHIFT,YSHIFT>] corners at XCOORD1 YCOORD1 
  1058. % **    and  XCOORD2 YCOORD2 
  1059. % **  Draws a rectangle with corners at (X1,Y1), (X2,Y1), (X1,Y2), (X2,Y2)
  1060. % **  Lines have thickness \linethickness, and overlap at the corners.
  1061. % **  The optional field  <XSHIFT,YSHIFT>  functions as with a \put command.
  1062. % **  See Subsection 4.2 of the manual.
  1063. \def\putrectangle{%
  1064.   \!ifnextchar<{\!putrectangle}{\!putrectangle<\!zpt,\!zpt> }}
  1065. \def\!putrectangle<#1,#2> corners at #3 #4 and #5 #6 {%
  1066. % ** get locations
  1067.   \!xone=\!M{#3}\!xunit  \!xtwo=\!M{#5}\!xunit%   
  1068.   \!yone=\!M{#4}\!yunit  \!ytwo=\!M{#6}\!yunit%           
  1069.   \ifdim \!xtwo<\!xone
  1070.     \!dimenI=\!xone  \!xone=\!xtwo  \!xtwo=\!dimenI
  1071.   \fi
  1072.   \ifdim \!ytwo<\!yone
  1073.     \!dimenI=\!yone  \!yone=\!ytwo  \!ytwo=\!dimenI
  1074.   \fi
  1075.   \!dimenI=#1\relax  \advance\!xone\!dimenI  \advance\!xtwo\!dimenI
  1076.   \!dimenI=#2\relax  \advance\!yone\!dimenI  \advance\!ytwo\!dimenI
  1077.   \let\!MRect=\!M%                  ** save current coord/dimen mode
  1078.   \!setdimenmode
  1079. % ** shade rectangle if appropriate
  1080.   \!shaderectangle
  1081. % ** draw horizontal edges
  1082.   \!dimenI=.5\linethickness
  1083.   \advance \!xone  -\!dimenI%       ** adjust x-location to overlap corners
  1084.   \advance \!xtwo   \!dimenI%       ** ditto
  1085.   \putrule from {\!xone} {\!yone} to {\!xtwo} {\!yone} 
  1086.   \putrule from {\!xone} {\!ytwo} to {\!xtwo} {\!ytwo} 
  1087. % ** draw vertical edges
  1088.   \advance \!xone   \!dimenI%       ** restore original x-values
  1089.   \advance \!xtwo  -\!dimenI% 
  1090.   \advance \!yone  -\!dimenI%       ** adjust y-location to overlap corners
  1091.   \advance \!ytwo   \!dimenI%       ** ditto
  1092.   \putrule from {\!xone} {\!yone} to {\!xone} {\!ytwo} 
  1093.   \putrule from {\!xtwo} {\!yone} to {\!xtwo} {\!ytwo} 
  1094.   \let\!M=\!MRect%                  ** restore coord/dimen mode
  1095.   \ignorespaces}
  1096. % ** \shaderectangleson 
  1097. % **   Subsequent rectangles will be shaded according to 
  1098. % **   the current shading pattern.  Affects \putrectangle, \putbar,
  1099. % **   \frame, \sethistograms, and \setbars. See Subsection 7.5 of the manual.
  1100. \def\shaderectangleson{%     
  1101.   \def\!shaderectangle{\!!shaderectangle}%
  1102.   \ignorespaces}
  1103. % ** \shaderectanglesoff 
  1104. % **    Suppresses  \shaderectangleson.  The default.
  1105. \def\shaderectanglesoff{%
  1106.   \def\!shaderectangle{}%
  1107.   \ignorespaces}
  1108. \shaderectanglesoff
  1109. % ** The following internal routine shades the current rectangle, when
  1110. % **   \!shaderectangle = \!!shaderectangle . 
  1111. \def\!!shaderectangle{%
  1112.   \!dimenA=\!xtwo  \advance \!dimenA -\!xone
  1113.   \!dimenB=\!ytwo  \advance \!dimenB -\!yone
  1114.   \ifdim \!dimenA<\!dimenB
  1115.     \!startvshade (\!xone,\!yone,\!ytwo)
  1116.     \!lshade      (\!xtwo,\!yone,\!ytwo)
  1117.   \else
  1118.     \!starthshade (\!yone,\!xone,\!xtwo)
  1119.     \!lshade      (\!ytwo,\!xone,\!xtwo)
  1120.   \fi
  1121.   \ignorespaces}
  1122. % ** \frame [<SEPARATION>] {TEXT}
  1123. % ** Draws a frame of thickness linethickness about the box enclosing
  1124. % **   TEXT; the frame is separated from the box by a distance of
  1125. % **   SEPARATION.  The result is an hbox with the same baseline as TEXT.
  1126. % **   If <SEPARATION> is omitted, you get the effect of <0pt>.
  1127. % ** See Subsection 4.2 of the manual.
  1128. \def\frame{%
  1129.   \!ifnextchar<{\!frame}{\!frame<\!zpt> }}
  1130. \long\def\!frame<#1> #2{%
  1131.   \beginpicture
  1132.     \setcoordinatesystem units <1pt,1pt> point at 0 0 
  1133.     \put {#2} [Bl] at 0 0 
  1134.     \!dimenA=#1\relax
  1135.     \!dimenB=\!wd \advance \!dimenB \!dimenA
  1136.     \!dimenC=\!ht \advance \!dimenC \!dimenA
  1137.     \!dimenD=\!dp \advance \!dimenD \!dimenA
  1138.     \let\!MFr=\!M
  1139.     \!setdimenmode
  1140.     \putrectangle corners at {-\!dimenA} {-\!dimenD} and {\!dimenB} {\!dimenC}
  1141.     \!setcoordmode
  1142.     \let\!M=\!MFr
  1143.   \endpicture
  1144.   \ignorespaces}
  1145. % ** \rectangle <WIDTH> <HEIGHT>
  1146. % ** Constructs a rectangle of width WIDTH and heigth HEIGHT. 
  1147. % ** See Subsection 4.2 of the manual.
  1148. \def\rectangle <#1> <#2> {%
  1149.   \setbox0=\hbox{}\wd0=#1\ht0=#2\frame {\box0}}
  1150. % *********************************************
  1151. % ***  CURVES  (Upper level \plot commands) ***
  1152. % *********************************************
  1153. % ** User commands
  1154. % **   \plot  DATA  /
  1155. % **   \plot  "FILE NAME"
  1156. % **   \setquadratic
  1157. % **   \setlinear
  1158. % **   \sethistograms
  1159. % **   \vshade  ...
  1160. % **   \hshade  ...
  1161. % \plot: multi-purpose command. Draws histograms, bar graphs, piecewise-linear
  1162. % or piecewise quadratic curves, depending on the setting of \!drawcurve.
  1163. % See Subsections 4.3-4.5, 5.1, 5.2 of the manual.
  1164. \def\plot{%
  1165.   \!ifnextchar"{\!plotfromfile}{\!drawcurve}}
  1166. \def\!plotfromfile"#1"{%
  1167.   \expandafter\!drawcurve \input #1 /}
  1168. % Command to set piecewise quadratic mode
  1169. % See Subsections 5.1, 7.3, and 7.4 of the manual.
  1170. \def\setquadratic{%
  1171.   \let\!drawcurve=\!qcurve
  1172.   \let\!!Shade=\!!qShade
  1173.   \let\!!!Shade=\!!!qShade}
  1174. % Command to set piecewise linear mode
  1175. % See Subsections 5.1, 7.3, and 7.4 of the manual.
  1176. \def\setlinear{%
  1177.   \let\!drawcurve=\!lcurve
  1178.   \let\!!Shade=\!!lShade
  1179.   \let\!!!Shade=\!!!lShade}
  1180. % Command to set histogram mode
  1181. % See Subsection 4.3 of the manual.
  1182. \def\sethistograms{%
  1183.   \let\!drawcurve=\!hcurve}
  1184. % Commands to cycle through list of coordinates in piecewise quadratic 
  1185. % interpolation mode
  1186. \def\!qcurve #1 #2 {%
  1187.   \!start (#1,#2)
  1188.   \!Qjoin}
  1189. \def\!Qjoin#1 #2 #3 #4 {%
  1190.   \!qjoin (#1,#2) (#3,#4)             % \!qjoin  is defined in QUADRATIC
  1191.   \!ifnextchar/{\!finish}{\!Qjoin}}
  1192. % Commands to cycle through list of coordinates in piecewise linear 
  1193. % interpolation mode
  1194. \def\!lcurve #1 #2 {%
  1195.   \!start (#1,#2)
  1196.   \!Ljoin}
  1197. \def\!Ljoin#1 #2 {%
  1198.   \!ljoin (#1,#2)                    % \!ljoin  is defined in LINEAR
  1199.   \!ifnextchar/{\!finish}{\!Ljoin}}
  1200. \def\!finish/{\ignorespaces}
  1201. % Command to cycle through list of coordinates in histogram mode
  1202. \def\!hcurve #1 #2 {%
  1203.   \edef\!hxS{#1}%
  1204.   \edef\!hyS{#2}%
  1205.   \!hjoin}
  1206. \def\!hjoin#1 #2 {%
  1207.   \putrectangle corners at {\!hxS} {\!hyS} and {#1} {#2}
  1208.   \edef\!hxS{#1}%
  1209.   \!ifnextchar/{\!finish}{\!hjoin}}
  1210. % \vshade: See Subsection 7.3 of the manual.
  1211. \def\vshade #1 #2 #3 {%
  1212.   \!startvshade (#1,#2,#3)
  1213.   \!Shadewhat}
  1214. % \hshade: See Subsection 7.4 of the manual.
  1215. \def\hshade #1 #2 #3 {%
  1216.   \!starthshade (#1,#2,#3)
  1217.   \!Shadewhat}
  1218. % Commands to cycle through coordinates and optional "edge effect"
  1219. % fields while shading.
  1220. \def\!Shadewhat{%
  1221.   \futurelet\!nextchar\!Shade}
  1222. \def\!Shade{%
  1223.   \if <\!nextchar
  1224.     \def\!nextShade{\!!Shade}%
  1225.   \else
  1226.     \if /\!nextchar
  1227.       \def\!nextShade{\!finish}%
  1228.     \else
  1229.       \def\!nextShade{\!!!Shade}%
  1230.     \fi
  1231.   \fi
  1232.   \!nextShade}
  1233. \def\!!lShade<#1> #2 #3 #4 {%
  1234.   \!lshade <#1> (#2,#3,#4)                 % \!lshade is defined in SHADING
  1235.   \!Shadewhat}
  1236. \def\!!!lShade#1 #2 #3 {%
  1237.   \!lshade (#1,#2,#3)
  1238.   \!Shadewhat} 
  1239. \def\!!qShade<#1> #2 #3 #4 #5 #6 #7 {%
  1240.   \!qshade <#1> (#2,#3,#4) (#5,#6,#7)      % \!qshade is defined in SHADING
  1241.   \!Shadewhat}
  1242. \def\!!!qShade#1 #2 #3 #4 #5 #6 {%
  1243.   \!qshade (#1,#2,#3) (#4,#5,#6)
  1244.   \!Shadewhat} 
  1245. % ** Set default interpolation mode
  1246. \setlinear
  1247. %  ********************************************
  1248. %  *** DASHPATTERNS (Sets up dash patterns) ***
  1249. %  ********************************************
  1250. %  **  User commands:
  1251. %  **    \setdashpattern <DIMEN1,DIMEN2,DIMEN3,...>
  1252. %  **    \setdots <INTRADOT_DISTANCE>
  1253. %  **    \setdotsnear <INTRADOT_DISTANCE> for <ARC LENGTH>
  1254. %  **    \setdashes <DASH/SKIP_DISTANCE>
  1255. %  **    \setdashesnear <DASH/SKIP_DISTANCE> for <ARC LENGTH>
  1256. %  **    \setsolid
  1257. %  **    \findlength {CURVE CMDS}
  1258. %  **  Internal commands:
  1259. %  **    \!dashingon
  1260. %  **    \!dashingoff
  1261. %  **  Dash patterns are specified by a balanced token list whose complete
  1262. %  **    expansion has the form: DIMEN1,DIMEN2,DIMEN3,DIMEN4,... ; this produces
  1263. %  **    an arc of length DIMEN1, a skip of length DIMEN2, an arc of length
  1264. %  **    DIMEN3, a skip of length DIMEN4, ... .  Any number of DIMEN values may
  1265. %  **    be given. The pattern is repeated as many times (perhaps fractional)
  1266. %  **    as necessary to draw the curve. 
  1267. %  **  A dash pattern remains in effect until it is overridden by a call to
  1268. %  **    \setdashpattern, or to \setdots, \setdotsnear ... , \setdashes, 
  1269. %  **    \setdashesnear ... , or \setsolid.
  1270. %  **  Solid lines are the default.
  1271. %  **  \def\setdashpattern <DIMEN1,DIMEN2,DIMEN3,...>
  1272. %  **  The following routine converts a balanced list of tokens whose
  1273. %  **  complete expansion has the form  DIMEN1,DIMEN2, ... , DIMENk  into 
  1274. %  **  three list macros that are used in drawing dashed rules and curves:
  1275. %  **    !Flist:   \!Rule{DIMEN1}\!Skip{DIMEN2}\!Rule{DIMEN3}\!Skip{DIMEN4} ...
  1276. %  **    !Blist:   ...\!Skip{DIMEN4}\!Rule{DIMEN3}\!Skip{DIMEN2}\!Rule{DIMEN1}
  1277. %  **    !UDlist:  \\{DIMEN1}\\{DIMEN2}\\{DIMEN3}\\{DIMEN4} ...;
  1278. %  **  calculates \!leaderlength := DIMEN1 + ... + DIMENk; and
  1279. %  **  sets the curve drawing routines to dash mode.
  1280. %  **  Those lists are used by the curve drawing routines.
  1281. %  **  Dimenj ... may be given as an explicit dimension (e.g., 5pt), or
  1282. %  **  as an expression involving a dimension register (e.g., -2.5\dimen0).
  1283. %  **  See Subsection 6.2 of the manual
  1284. \def\setdashpattern <#1>{%
  1285.   \def\!Flist{}\def\!Blist{}\def\!UDlist{}%
  1286.   \!countA=0
  1287.   \!ecfor\!item:=#1\do{%
  1288.     \!dimenA=\!item\relax
  1289.     \expandafter\!rightappend\the\!dimenA\withCS{\\}\to\!UDlist%
  1290.     \advance\!countA  1
  1291.     \ifodd\!countA
  1292.       \expandafter\!rightappend\the\!dimenA\withCS{\!Rule}\to\!Flist%
  1293.       \expandafter\!leftappend\the\!dimenA\withCS{\!Rule}\to\!Blist%
  1294.     \else 
  1295.       \expandafter\!rightappend\the\!dimenA\withCS{\!Skip}\to\!Flist%
  1296.       \expandafter\!leftappend\the\!dimenA\withCS{\!Skip}\to\!Blist%
  1297.     \fi}%
  1298.   \!leaderlength=\!zpt
  1299.   \def\!Rule##1{\advance\!leaderlength  ##1}%
  1300.   \def\!Skip##1{\advance\!leaderlength  ##1}%
  1301.   \!Flist%
  1302.   \ifdim\!leaderlength>\!zpt 
  1303.   \else
  1304.     \def\!Flist{\!Skip{24in}}\def\!Blist{\!Skip{24in}}\ignorespaces
  1305.     \def\!UDlist{\\{\!zpt}\\{24in}}\ignorespaces
  1306.     \!leaderlength=24in
  1307.   \fi
  1308.   \!dashingon}   
  1309. %  **  \!dashingon  -- puts the curve drawing routines into dash mode
  1310. %  **  \!dashingoff -- puts the curve drawing routines into solid mode
  1311. %  **  These are internal commands, invoked by \setdashpattern and \setsolid
  1312. \def\!dashingon{%
  1313.   \def\!advancedashing{\!!advancedashing}%
  1314.   \def\!drawlinearsegment{\!lineardashed}%
  1315.   \def\!puthline{\!putdashedhline}%
  1316.   \def\!putvline{\!putdashedvline}%
  1317. %  \def\!putsline{\!putdashedsline}%
  1318.   \ignorespaces}% 
  1319. \def\!dashingoff{%
  1320.   \def\!advancedashing{\relax}%
  1321.   \def\!drawlinearsegment{\!linearsolid}%
  1322.   \def\!puthline{\!putsolidhline}%
  1323.   \def\!putvline{\!putsolidvline}%
  1324. %  \def\!putsline{\!putsolidsline}%
  1325.   \ignorespaces}
  1326. %  **  \setdots <LENGTH>  --  sets up a dot/skip pattern where dot (actually
  1327. %  **    the current plotsymbol) is plunked down once for every LENGTH 
  1328. %  **    traveled along the curve.  LENGTH defaults to 5pt.
  1329. %  **    See Subsection 6.1 of the manual.
  1330. \def\setdots{%
  1331.   \!ifnextchar<{\!setdots}{\!setdots<5pt>}}
  1332. \def\!setdots<#1>{%
  1333.   \!dimenB=#1\advance\!dimenB -\plotsymbolspacing
  1334.   \ifdim\!dimenB<\!zpt
  1335.     \!dimenB=\!zpt
  1336.   \fi
  1337. \setdashpattern <\plotsymbolspacing,\!dimenB>}
  1338. % ** \setdotsnear <LENGTH> for <ARC LENGTH>
  1339. % ** sets up a dot pattern where the dots are approximately LENGTH apart,
  1340. % ** the total length of the pattern is ARC LENGTH, and the pattern
  1341. % ** begins and ends with a dot. See Subsection 6.3 of the manual.
  1342. \def\setdotsnear <#1> for <#2>{%
  1343.   \!dimenB=#2\relax  \advance\!dimenB -.05pt  
  1344.   \!dimenC=#1\relax  \!countA=\!dimenC 
  1345.   \!dimenD=\!dimenB  \advance\!dimenD .5\!dimenC  \!countB=\!dimenD
  1346.   \divide \!countB  \!countA
  1347.   \ifnum 1>\!countB 
  1348.     \!countB=1
  1349.   \fi
  1350.   \divide\!dimenB  \!countB
  1351.   \setdots <\!dimenB>}
  1352. %  **  \setdashes <LENGTH>  --  sets up a dash/skip pattern where the dash
  1353. %  **    and the skip are each of length LENGTH (the dash is formed by
  1354. %  **    plunking down the current plotsymbol over an arc of length LENGTH
  1355. %  **    and so may actually be longer than LENGTH.  LENGTH defaults to 5pt.
  1356. %  **    See Subsection 6.1 of the manual.
  1357. \def\setdashes{%
  1358.   \!ifnextchar<{\!setdashes}{\!setdashes<5pt>}}
  1359. \def\!setdashes<#1>{\setdashpattern <#1,#1>}
  1360. % ** \setdashesnear ...
  1361. % ** Like \setdotsnear; the pattern begins and ends with a dash.
  1362. % ** See Subsection 6.3 of the manual.
  1363. \def\setdashesnear <#1> for <#2>{%
  1364.   \!dimenB=#2\relax  
  1365.   \!dimenC=#1\relax  \!countA=\!dimenC 
  1366.   \!dimenD=\!dimenB  \advance\!dimenD .5\!dimenC  \!countB=\!dimenD
  1367.   \divide \!countB  \!countA
  1368.   \ifodd \!countB 
  1369.   \else 
  1370.     \advance \!countB  1
  1371.   \fi
  1372.   \divide\!dimenB  \!countB
  1373.   \setdashes <\!dimenB>}
  1374. %  **  \setsolid  --  puts the curve drawing routines in "solid line" mode,
  1375. %  **    the default mode.  See Subsection 6.1 of the manual.
  1376. \def\setsolid{%
  1377.   \def\!Flist{\!Rule{24in}}\def\!Blist{\!Rule{24in}}%  
  1378.   \def\!UDlist{\\{24in}\\{\!zpt}}%
  1379.   \!dashingoff}  
  1380. \setsolid
  1381. %  **  \findlength {CURVE CMDS}
  1382. %  **  PiCTeX executes the \start, \ljoin, and \qjoin cmds comprising
  1383. %  **  CURVE CMDS without plotting anything, but stashes the length
  1384. %  **  of the phantom curve away in \totalarclength.
  1385. %  **  See Subsection 6.3 of the manual.
  1386. \def\findlength#1{%
  1387.   \begingroup
  1388.     \setdashpattern <0pt, \maxdimen>
  1389.     \setplotsymbol ({})  
  1390.     \dontsavelinesandcurves
  1391.     #1%
  1392.   \endgroup
  1393.   \ignorespaces}
  1394. % *************************************************************
  1395. % *** DIVISION  (Does long division of dimension registers) ***
  1396. % *************************************************************
  1397. % ** User command:
  1398. % **   \Divide {DIVIDEND} by {DIVISOR} forming {RESULT}
  1399. % ** Internal command
  1400. % **   \!divide{DIVIDEND}{DIVISOR}{RESULT}
  1401. % **  \!divide DIVIDEND [by] DIVISOR [to get] ANSWER
  1402. % **  Divides the dimension DIVIDEND by the dimension DIVISOR, placing the 
  1403. % **  quotient in the dimension register ANSWER.  Values are understood to 
  1404. % **  be in points.  E.g.  12.5pt/1.4pt=8.92857pt.
  1405. % **  Quotient is accurate to 1/65536pt=2**[-16]pt
  1406. % **  |DIVISOR| should be < 2048pt (about 28 inches).
  1407. \def\!divide#1#2#3{%
  1408.   \!dimenB=#1%                      **  dimB  holds current remainder (r)
  1409.   \!dimenC=#2%                      **  dimC  holds divisor (d)
  1410.   \!dimenD=\!dimenB%                **  dimD  holds quotient q=r/d for this 
  1411.   \divide \!dimenD \!dimenC%        **    step, in units of scaled pts
  1412.   \!dimenA=\!dimenD%                **  dimA  eventually holds answer (a)
  1413.   \multiply\!dimenD \!dimenC%       **  r <-- r - dq
  1414.   \advance\!dimenB -\!dimenD%       **  First step complete. Have integer part
  1415. %                                   **  of a, and corresponding remainder.
  1416.   \!dimenD=\!dimenC%                **  Temporarily use dimD to hold |d|
  1417.     \ifdim\!dimenD<\!zpt \!dimenD=-\!dimenD 
  1418.   \fi
  1419.   \ifdim\!dimenD<64pt%              **  Branch on the magnitude of |d|
  1420.     \!divstep[\!tfs]\!divstep[\!tfs]%
  1421.   \else 
  1422.     \!!divide
  1423.   \fi
  1424.   #3=\!dimenA\ignorespaces}
  1425. % **  The following code handles divisors  d  with 
  1426. % **    (1)  .88in =  64pt <= d <  256pt =  3.54in
  1427. % **    (2) 3.54in = 256pt <= d < 2048pt = 28.34in
  1428. % **  Anything bigger than that may result in an overflow condition.
  1429. % **  For our purposes, we should never even see case (2).
  1430. \def\!!divide{%
  1431.   \ifdim\!dimenD<256pt
  1432.     \!divstep[64]\!divstep[32]\!divstep[32]%
  1433.   \else 
  1434.     \!divstep[8]\!divstep[8]\!divstep[8]\!divstep[8]\!divstep[8]%
  1435.     \!dimenA=2\!dimenA
  1436.   \fi}
  1437. % **  The following macro does the real long division work.
  1438. \def\!divstep[#1]{%                 **  #1 = "B"
  1439.   \!dimenB=#1\!dimenB%              **  r <-- B*r
  1440.   \!dimenD=\!dimenB%                **  dimD  holds quotient q=r/d for this 
  1441.     \divide \!dimenD by \!dimenC%   **    step, in units of scaled pts
  1442.   \!dimenA=#1\!dimenA%              **  a <-- B*a + q
  1443.     \advance\!dimenA by \!dimenD%
  1444.   \multiply\!dimenD by \!dimenC%    **  r <-- r - dq
  1445.     \advance\!dimenB by -\!dimenD}
  1446. % **  \Divide:  See Subsection 9.3 of the manual.
  1447. \def\Divide <#1> by <#2> forming <#3> {%
  1448.   \!divide{#1}{#2}{#3}}
  1449. % *********************************************
  1450. % *** ELLIPSES (Draws ellipses and circles) ***
  1451. % *********************************************
  1452. % ** User commands
  1453. % **   \ellipticalarc  axes ratio A:B  DEGREES degrees from XSTART YSTART 
  1454. % **      center at XCENTER YCENTER 
  1455. % **   \circulararc DEGREES degrees from XSTART YSTART 
  1456. % **      center at XCENTER YCENTER 
  1457. % ** Internal command
  1458. % **   \!sinandcos{32*ANGLE in radians}{32*SIN}{32*COS}
  1459. % **   \ellipticalarc  axes ratio A:B  DEGREES degrees from XSTART YSTART 
  1460. % **      center at XCENTER YCENTER 
  1461. % **    Draws a elliptical arc starting at the coordinate point (XSTART,YSTART).
  1462. % **    The center of the ellipse of which the arc is a segment is at 
  1463. % **      (XCENTER,YCENTER).
  1464. % **    The arc extends through an angle of DEGREES degrees (may be + or -).
  1465. % **    A:B is the ratio of the length of the xaxis to the length of
  1466. % **      the yaxis of the ellipse
  1467. % **    Sqrt{[(XSTART-XCENTER)/A]**2 + [(YSTART-YCENTER)/B]**2}
  1468. % **      must be < 512pt (about 7in).
  1469. % **    Doesn't modify the dimensions (ht, dp, wd) of the PiCture under
  1470. % **      construction.
  1471. % ** \circulararc  --  See Subsection 5.3 of the manual.
  1472. \def\circulararc{%
  1473.   \ellipticalarc axes ratio 1:1 }
  1474. % ** \ellipticalarc  --  See Subsection 5.3 of the manual.
  1475. \def\ellipticalarc axes ratio #1:#2 #3 degrees from #4 #5 center at #6 #7 {%
  1476.   \!angle=#3pt\relax%                    ** get angle
  1477.   \ifdim\!angle>\!zpt 
  1478.     \def\!sign{}%                        ** counterclockwise
  1479.   \else 
  1480.     \def\!sign{-}\!angle=-\!angle%       ** clockwise
  1481.   \fi
  1482.   \!xxloc=\!M{#6}\!xunit%                ** convert CENTER to dimension
  1483.   \!yyloc=\!M{#7}\!yunit     
  1484.   \!xxS=\!M{#4}\!xunit%                  ** get STARTing point on rim of ellipse
  1485.   \!yyS=\!M{#5}\!yunit
  1486.   \advance\!xxS -\!xxloc%                ** make center of ellipse (0,0)
  1487.   \advance\!yyS -\!yyloc
  1488.   \!divide\!xxS{#1pt}\!xxS %             ** scale point on ellipse to point on 
  1489.   \!divide\!yyS{#2pt}\!yyS %                 corresponding circle
  1490.   \let\!MC=\!M%                          ** save current c/d mode
  1491.   \!setdimenmode%                        ** go into dimension mode
  1492.   \!xS=#1\!xxS  \advance\!xS\!xxloc
  1493.   \!yS=#2\!yyS  \advance\!yS\!yyloc
  1494.   \!start (\!xS,\!yS)%
  1495.   \!loop\ifdim\!angle>14.9999pt%         ** draw in major portion of ellipse 
  1496.     \!rotate(\!xxS,\!yyS)by(\!cos,\!sign\!sin)to(\!xxM,\!yyM) 
  1497.     \!rotate(\!xxM,\!yyM)by(\!cos,\!sign\!sin)to(\!xxE,\!yyE)
  1498.     \!xM=#1\!xxM  \advance\!xM\!xxloc  \!yM=#2\!yyM  \advance\!yM\!yyloc
  1499.     \!xE=#1\!xxE  \advance\!xE\!xxloc  \!yE=#2\!yyE  \advance\!yE\!yyloc
  1500.     \!qjoin (\!xM,\!yM) (\!xE,\!yE)
  1501.     \!xxS=\!xxE  \!yyS=\!yyE 
  1502.     \advance \!angle -15pt
  1503.   \repeat
  1504.   \ifdim\!angle>\!zpt%                   ** complete remaining arc, if any
  1505.     \!angle=100.53096\!angle%            ** convert angle to radians, divide
  1506.     \divide \!angle 360 %                **   by 2, and multiply by 32
  1507.     \!sinandcos\!angle\!!sin\!!cos%      ** get 32*sin & 32*cos
  1508.     \!rotate(\!xxS,\!yyS)by(\!!cos,\!sign\!!sin)to(\!xxM,\!yyM) 
  1509.     \!rotate(\!xxM,\!yyM)by(\!!cos,\!sign\!!sin)to(\!xxE,\!yyE)
  1510.     \!xM=#1\!xxM  \advance\!xM\!xxloc  \!yM=#2\!yyM  \advance\!yM\!yyloc
  1511.     \!xE=#1\!xxE  \advance\!xE\!xxloc  \!yE=#2\!yyE  \advance\!yE\!yyloc
  1512.     \!qjoin (\!xM,\!yM) (\!xE,\!yE)
  1513.   \fi
  1514.   \let\!M=\!MC%                          ** restore c/d mode
  1515.   \ignorespaces}%                        **   if appropriate
  1516. %  ** \!rotate(XREG,YREG)by(32cos,32sin)to(XXREG,YYREG)
  1517. %  ** rotates (XREG,YREG) by angle with specfied scaled cos & sin to
  1518. %  ** (XXREG,YYREG).  Uses \!dimenA & \!dimenB as scratch registers.
  1519. \def\!rotate(#1,#2)by(#3,#4)to(#5,#6){% 
  1520.   \!dimenA=#3#1\advance \!dimenA -#4#2%   ** Rcos(x+t)=Rcosx*cost - Rsinx*sint
  1521.   \!dimenB=#3#2\advance \!dimenB  #4#1%   ** Rsin(x+t)=Rsinx*cost + Rcosx*sint
  1522.   \divide \!dimenA 32  \divide \!dimenB 32 
  1523.   #5=\!dimenA  #6=\!dimenB
  1524.   \ignorespaces}
  1525. \def\!sin{4.17684}%                       ** 32*sin(pi/24) (pi/24=7.5deg)
  1526. \def\!cos{31.72624}%                      ** 32*cos(pi/24)
  1527. %  ** \!sinandcos{32*ANGLE in radians}{\SINCS}{\COSCS}
  1528. %  **   Computes the 32*sine and 32*cosine of a small ANGLE expressed in 
  1529. %  **   radians/32 and puts these values in the replacement texts of 
  1530. %  **   \SINCS and \COSCS
  1531. \def\!sinandcos#1#2#3{%
  1532.  \!dimenD=#1%                **  angle is expressed in radians/32: 1pt = 1/32rad
  1533.  \!dimenA=\!dimenD%          **  dimA will eventually contain 32sin(angle)in pts
  1534.  \!dimenB=32pt%              **  dimB will eventually contain 32cos(angle)in pts
  1535.  \!removept\!dimenD\!value%  **  get value of 32*angle, without "pt"
  1536.  \!dimenC=\!dimenD%          **  holds 32*angle**i/i! in pts
  1537.  \!dimenC=\!value\!dimenC \divide\!dimenC by 64 %   ** now 32*angle**2/2
  1538.  \advance\!dimenB by -\!dimenC%                     ** 32-32*angle**2/2
  1539.  \!dimenC=\!value\!dimenC \divide\!dimenC by 96 %   ** now 32*angle**3/3!
  1540.  \advance\!dimenA by -\!dimenC%                     ** now 32*(angle-angle**3/6)
  1541.  \!dimenC=\!value\!dimenC \divide\!dimenC by 128 %  ** now 32*angle**4/4!
  1542.  \advance\!dimenB by \!dimenC%
  1543.  \!removept\!dimenA#2%                              ** set 32*sin(angle)
  1544.  \!removept\!dimenB#3%                              ** set 32*cos(angle)
  1545.  \ignorespaces}
  1546. % *****************************************************************
  1547. % ***  RULES  (Draws rules, i.e., horizontal & vertical lines)  ***
  1548. % *****************************************************************
  1549. % **  User command:
  1550. % **    \putrule [<XDIMEN,YDIMEN>] from  XCOORD1 YCOORD1 
  1551. % **      to  XCOORD2 YCOORD2 
  1552. % **  Internal commands:
  1553. % **    \!puthline [<XDIMEN,YDIMEN>]    (h = horizontal)
  1554. % **      Set by dashpat to either: \!putsolidhline  or \!putdashedhline
  1555. % **    \!putvline [<XDIMEN,YDIMEN>]    (v = vertical)
  1556. % **      Either:  \!putsolidvline  or  \!putdashedvline
  1557. % **  \putrule [<XDIMEN,YDIMEN>] from XCOORD1 YCOORD1
  1558. % **    to XCOORD2 YCOORD2
  1559. % **  Draws a rule -- dashed or solid depending on the current dash pattern --
  1560. % **    from (X1,Y1) to (X2,Y2).  Uses TEK's  \hrule & \vrule & \leaders  
  1561. % **    constructions to handle horizontal & vertical lines efficiently both
  1562. % **    in terms of execution time and space in the DVI file.  
  1563. % **  See Subsection 4.1 of the manual.
  1564. \def\putrule#1from #2 #3 to #4 #5 {%
  1565.   \!xloc=\!M{#2}\!xunit  \!xxloc=\!M{#4}\!xunit%   
  1566.   \!yloc=\!M{#3}\!yunit  \!yyloc=\!M{#5}\!yunit%           
  1567.   \!dxpos=\!xxloc  \advance\!dxpos by -\!xloc
  1568.   \!dypos=\!yyloc  \advance\!dypos by -\!yloc
  1569.   \ifdim\!dypos=\!zpt
  1570.     \def\!!Line{\!puthline{#1}}\ignorespaces
  1571.   \else
  1572.     \ifdim\!dxpos=\!zpt
  1573.       \def\!!Line{\!putvline{#1}}\ignorespaces
  1574.     \else 
  1575.        \def\!!Line{}
  1576.     \fi
  1577.   \fi
  1578.   \let\!ML=\!M%           ** save current coord\dimen mode
  1579.   \!setdimenmode%         ** express locations in dimens
  1580.   \!!Line%
  1581.   \let\!M=\!ML%           ** restore previous c/d mode
  1582.   \ignorespaces}
  1583. % **  \!putsolidhline [<XDIMEN,YDIMEN>]
  1584. % **  Place horizontal solid line
  1585. \def\!putsolidhline#1{%
  1586.   \ifdim\!dxpos>\!zpt 
  1587.     \put{\!hline\!dxpos}#1[l] at {\!xloc} {\!yloc}
  1588.   \else 
  1589.     \put{\!hline{-\!dxpos}}#1[l] at {\!xxloc} {\!yyloc}
  1590.   \fi
  1591.   \ignorespaces}
  1592. % **  \!putsolidvline [shifted <XDIMEN,YDIMEN>]
  1593. % **  Place vertical solid line
  1594. \def\!putsolidvline#1{%
  1595.   \ifdim\!dypos>\!zpt 
  1596.     \put{\!vline\!dypos}#1[b] at {\!xloc} {\!yloc}
  1597.   \else 
  1598.     \put{\!vline{-\!dypos}}#1[b] at {\!xxloc} {\!yyloc}
  1599.   \fi
  1600.   \ignorespaces}
  1601. \def\!hline#1{\hbox to #1{\leaders \hrule height\linethickness\hfill}}
  1602. \def\!vline#1{\vbox to #1{\leaders \vrule width\linethickness\vfill}}
  1603. % **  \!putdashedhline [<XDIMEN,YDIMEN>]
  1604. % **  Place dashed horizontal line
  1605. \def\!putdashedhline#1{%
  1606.   \ifdim\!dxpos>\!zpt 
  1607.     \!DLsetup\!Flist\!dxpos
  1608.     \put{\hbox to \!totalleaderlength{\!hleaders}\!hpartialpattern\!Rtrunc}
  1609.       #1[l] at {\!xloc} {\!yloc} 
  1610.   \else 
  1611.     \!DLsetup\!Blist{-\!dxpos}
  1612.     \put{\!hpartialpattern\!Ltrunc\hbox to \!totalleaderlength{\!hleaders}}
  1613.       #1[r] at {\!xloc} {\!yloc} 
  1614.   \fi
  1615.   \ignorespaces}
  1616. % **  \!putdashedhline [<XDIMEN,YDIMEN>]
  1617. % **  Place dashed vertical line
  1618. \def\!putdashedvline#1{%
  1619.   \!dypos=-\!dypos%            ** vertical leaders go from top to bottom
  1620.   \ifdim\!dypos>\!zpt 
  1621.     \!DLsetup\!Flist\!dypos 
  1622.     \put{\vbox{\vbox to \!totalleaderlength{\!vleaders}
  1623.       \!vpartialpattern\!Rtrunc}}#1[t] at {\!xloc} {\!yloc} 
  1624.   \else 
  1625.     \!DLsetup\!Blist{-\!dypos}
  1626.     \put{\vbox{\!vpartialpattern\!Ltrunc
  1627.       \vbox to \!totalleaderlength{\!vleaders}}}#1[b] at {\!xloc} {\!yloc} 
  1628.   \fi
  1629.   \ignorespaces}
  1630. % **  The rest of the macros in this section are subroutines used by 
  1631. % **  \!putdashedhline and \!putdashedvline.
  1632. \def\!DLsetup#1#2{%            ** Dashed-Line set up
  1633.   \let\!RSlist=#1%             ** set !Rule-Skip list
  1634.   \!countB=#2%                 ** convert rule length to integer (number of sps)
  1635.   \!countA=\!leaderlength%     ** ditto, leaderlength
  1636.   \divide\!countB by \!countA% ** number of complete leader units
  1637.   \!totalleaderlength=\!countB\!leaderlength
  1638.   \!Rresiduallength=#2%
  1639.   \advance \!Rresiduallength by -\!totalleaderlength%  \** excess length
  1640.   \!Lresiduallength=\!leaderlength
  1641.   \advance \!Lresiduallength by -\!Rresiduallength
  1642.   \ignorespaces}
  1643. \def\!hleaders{%
  1644.   \def\!Rule##1{\vrule height\linethickness width##1}%
  1645.   \def\!Skip##1{\hskip##1}%
  1646.   \leaders\hbox{\!RSlist}\hfill}
  1647. \def\!hpartialpattern#1{%
  1648.   \!dimenA=\!zpt \!dimenB=\!zpt 
  1649.   \def\!Rule##1{#1{##1}\vrule height\linethickness width\!dimenD}%
  1650.   \def\!Skip##1{#1{##1}\hskip\!dimenD}%
  1651.   \!RSlist}
  1652. \def\!vleaders{%
  1653.   \def\!Rule##1{\hrule width\linethickness height##1}%
  1654.   \def\!Skip##1{\vskip##1}%
  1655.   \leaders\vbox{\!RSlist}\vfill}
  1656. \def\!vpartialpattern#1{%
  1657.   \!dimenA=\!zpt \!dimenB=\!zpt 
  1658.   \def\!Rule##1{#1{##1}\hrule width\linethickness height\!dimenD}%
  1659.   \def\!Skip##1{#1{##1}\vskip\!dimenD}%
  1660.   \!RSlist}
  1661. \def\!Rtrunc#1{\!trunc{#1}>\!Rresiduallength}
  1662. \def\!Ltrunc#1{\!trunc{#1}<\!Lresiduallength}
  1663. \def\!trunc#1#2#3{%          
  1664.   \!dimenA=\!dimenB         
  1665.   \advance\!dimenB by #1%
  1666.   \!dimenD=\!dimenB  \ifdim\!dimenD#2#3\!dimenD=#3\fi
  1667.   \!dimenC=\!dimenA  \ifdim\!dimenC#2#3\!dimenC=#3\fi
  1668.   \advance \!dimenD by -\!dimenC}
  1669. %  ****************************************************************
  1670. %  ***  LINEAR ARC  (Draws straight lines -- solid and dashed)  ***
  1671. %  ****************************************************************
  1672. %  **  User commands
  1673. %  **    \inboundscheckoff
  1674. %  **    \inboundscheckon
  1675. %  **  Internal commands 
  1676. %  **    \!start (XCOORD,YCOORD)
  1677. %  **    \!ljoin (XCOORD,YCOORD)
  1678. %  **    \!drawlinearsegment  --  set by \dashpat to either
  1679. %  **      \!linearsolid  or  \!lineardashed
  1680. %  **    \!advancedashing     --  set by \dashpat to either
  1681. %  **       \relax  or  \!!advancedashing
  1682. %  **    \!plotifinbounds     --  set by \inboundscheck off/on to either
  1683. %  **       \!plot  or  \!!plotifinbounds
  1684. %  **    \!initinboundscheck  --  set by \inboundscheck off/on to either
  1685. %  **       \relax  or  \!!initinboundscheck
  1686. %  \plotsymbolspacing  ** distance between consecutive plot positions
  1687. %  \!xS                ** starting x
  1688. %  \!yS                ** starting y
  1689. %  \!xE                ** ending   x
  1690. %  \!yE                ** ending   y
  1691. %  \!xdiff             ** x_end - x_start
  1692. %  \!ydiff             ** y_end - y_start
  1693. %  \!distacross        ** how far along curve next point to be plotted is
  1694. %  \!arclength         ** approximate length of arc for current interval
  1695. %  \!downlength        ** remaining length for "pen" to be down    
  1696. %  \!uplength          ** length for "pen" to be down    
  1697. %  \!intervalno        ** counts segments to curve
  1698. %  \totalarclength     ** cumulative distance along curve
  1699. %  \!npoints           ** approximately  (arc length / plotsymbolspacing)
  1700. %  **  Calls -- \!Pythag, \!divide, \!plot
  1701. %  **  \!start (XCOORD,YCOORD)
  1702. %  **  Sets initial point for linearly (or quadratically) interpolated curve
  1703. \def\!start (#1,#2){%
  1704.   \!plotxorigin=\!xorigin  \advance \!plotxorigin by \!plotsymbolxshift
  1705.   \!plotyorigin=\!yorigin  \advance \!plotyorigin by \!plotsymbolyshift
  1706.   \!xS=\!M{#1}\!xunit \!yS=\!M{#2}\!yunit
  1707.   \!rotateaboutpivot\!xS\!yS
  1708.   \!copylist\!UDlist\to\!!UDlist% **\!UDlist has the form \\{dimen1}\\{dimen2}..
  1709. %                                 ** Routine will draw dashed line with pen
  1710. %                                 ** down for dimen1, up for dimen2, ...
  1711.   \!getnextvalueof\!downlength\from\!!UDlist
  1712.   \!distacross=\!zpt%             ** 1st point goes at start of curve
  1713.   \!intervalno=0 %                ** initialize interval counter
  1714.   \global\totalarclength=\!zpt%   ** initialize distance traveled along curve
  1715.   \ignorespaces}
  1716. %  **  \!ljoin (XCOORD,YCOORD) 
  1717. %  **  Draws a straight line starting at the last point specified
  1718. %  **    by the most recent \!start, \!ljoin, or \!qjoin, and
  1719. %  **    ending at (XCOORD,YCOORD).
  1720. \def\!ljoin (#1,#2){%
  1721.   \advance\!intervalno by 1
  1722.   \!xE=\!M{#1}\!xunit \!yE=\!M{#2}\!yunit
  1723.   \!rotateaboutpivot\!xE\!yE
  1724.   \!xdiff=\!xE \advance \!xdiff by -\!xS%**  xdiff = xE - xS
  1725.   \!ydiff=\!yE \advance \!ydiff by -\!yS%**  ydiff = yE - yS
  1726.   \!Pythag\!xdiff\!ydiff\!arclength%     **  arclength = sqrt(xdiff**2+ydiff**2) 
  1727.   \global\advance \totalarclength by \!arclength%
  1728.   \!drawlinearsegment%   ** set by dashpat to \!linearsolid or \!lineardashed
  1729.   \!xS=\!xE \!yS=\!yE%   ** shift ending points to starting points
  1730.   \ignorespaces}
  1731. % **  The following routine is used to draw a "solid" line between (xS,yS)
  1732. % **  and (xE,yE).  Points are spaced nearly every  \plotsymbolspacing length
  1733. % **  along the line.  
  1734. \def\!linearsolid{%
  1735.   \!npoints=\!arclength
  1736.   \!countA=\plotsymbolspacing
  1737.   \divide\!npoints by \!countA%      ** now #pts =. arclength/plotsymbolspacing
  1738.   \ifnum \!npoints<1 
  1739.     \!npoints=1 
  1740.   \fi
  1741.   \divide\!xdiff by \!npoints
  1742.   \divide\!ydiff by \!npoints
  1743.   \!xpos=\!xS \!ypos=\!yS
  1744.   \loop\ifnum\!npoints>-1
  1745.     \!plotifinbounds
  1746.     \advance \!xpos by \!xdiff
  1747.     \advance \!ypos by \!ydiff
  1748.     \advance \!npoints by -1
  1749.   \repeat
  1750.   \ignorespaces}
  1751. % ** The following routine is used to draw a dashed line between (xS,yS)
  1752. % ** and (xE,yE). The dash pattern continues from the previous segment.
  1753. \def\!lineardashed{%
  1754.   \ifdim\!distacross>\!arclength
  1755.     \advance \!distacross by -\!arclength  %nothing to plot in this interval
  1756.   \else
  1757.     \loop\ifdim\!distacross<\!arclength
  1758. %     ** plot point, interpolating linearly in x and y
  1759.       \!divide\!distacross\!arclength\!dimenA%  ** dimA = across/arclength
  1760.       \!removept\!dimenA\!t%  ** \!t holds value in dimA, without the "pt"
  1761.       \!xpos=\!t\!xdiff \advance \!xpos by \!xS
  1762.       \!ypos=\!t\!ydiff \advance \!ypos by \!yS
  1763.       \!plotifinbounds
  1764.       \advance\!distacross by \plotsymbolspacing
  1765.       \!advancedashing
  1766.     \repeat  
  1767.     \advance \!distacross by -\!arclength%    ** prepare for next interval 
  1768.   \fi
  1769.   \ignorespaces}
  1770. \def\!!advancedashing{%
  1771.   \advance\!downlength by -\plotsymbolspacing
  1772.   \ifdim \!downlength>\!zpt
  1773.   \else
  1774.     \advance\!distacross by \!downlength
  1775.     \!getnextvalueof\!uplength\from\!!UDlist
  1776.     \advance\!distacross by \!uplength
  1777.     \!getnextvalueof\!downlength\from\!!UDlist
  1778.   \fi}
  1779. % ** \inboundscheckoff & \inboundscheckon: See Subsection 5.5 of the manual.
  1780. \def\inboundscheckoff{%
  1781.   \def\!plotifinbounds{\!plot(\!xpos,\!ypos)}%
  1782.   \def\!initinboundscheck{\relax}\ignorespaces}
  1783. \def\inboundscheckon{%
  1784.   \def\!plotifinbounds{\!!plotifinbounds}%
  1785.   \def\!initinboundscheck{\!!initinboundscheck}%
  1786.   \!initinboundscheck\ignorespaces} 
  1787. \inboundscheckoff
  1788. % ** The following code plots the current point only if it falls in the
  1789. % ** current plotarea.  It doesn't matter if the coordinate system has
  1790. % ** changed since the plotarea was set up.  However, shifts of the plot
  1791. % ** are ignored (how the plotsymbol stands relative to its plot position is
  1792. % ** unknown anyway).
  1793. \def\!!plotifinbounds{%
  1794.   \ifdim \!xpos<\!checkleft
  1795.   \else
  1796.     \ifdim \!xpos>\!checkright
  1797.     \else
  1798.       \ifdim \!ypos<\!checkbot
  1799.       \else
  1800.          \ifdim \!ypos>\!checktop
  1801.          \else
  1802.            \!plot(\!xpos,\!ypos)
  1803.          \fi 
  1804.       \fi
  1805.     \fi
  1806.   \fi}
  1807. \def\!!initinboundscheck{%
  1808.   \!checkleft=\!arealloc     \advance\!checkleft by \!xorigin
  1809.   \!checkright=\!arearloc    \advance\!checkright by \!xorigin
  1810.   \!checkbot=\!areabloc      \advance\!checkbot by \!yorigin
  1811.   \!checktop=\!areatloc      \advance\!checktop by \!yorigin}
  1812. % *********************************
  1813. % *** LOGTEN  (Log_10 function) ***
  1814. % *********************************
  1815. % ** \!logten{X}
  1816. % ** Calculates log_10 of X.  X and LOG10(X) are in fixed point notation.
  1817. % **  X must be positive; it may have an optional `+' sign; any number
  1818. % **  of digits may be specified for X.  The absolute error in LOG10(X) is
  1819. % **  less than .0001 (probably < .00006).  That's about as good as you
  1820. % **  hope for, since TEX only operates to 5 figures after the decimal
  1821. % **  point anyway.
  1822. %  \!rootten=3.162278pt       **** These are values are set in ALLOCATIONS
  1823. %  \!tenAe=2.543275pt  (=A5)
  1824. %  \!tenAc=2.773839pt  (=A3)
  1825. %  \!tenAa=8.690286pt  (=A1)
  1826. \def\!logten#1#2{%
  1827.   \expandafter\!!logten#1\!nil
  1828.   \!removept\!dimenF#2%
  1829.   \ignorespaces}
  1830. \def\!!logten#1#2\!nil{%
  1831.   \if -#1%
  1832.     \!dimenF=\!zpt
  1833.     \def\!next{\ignorespaces}%
  1834.   \else
  1835.     \if +#1%
  1836.       \def\!next{\!!logten#2\!nil}%
  1837.     \else
  1838.       \if .#1%
  1839.         \def\!next{\!!logten0.#2\!nil}%
  1840.       \else
  1841.         \def\!next{\!!!logten#1#2..\!nil}%
  1842.       \fi
  1843.     \fi
  1844.   \fi
  1845.   \!next}
  1846. \def\!!!logten#1#2.#3.#4\!nil{%
  1847.   \!dimenF=1pt %                 ** DimF holds log10 original argument
  1848.   \if 0#1%                      
  1849.     \!!logshift#3pt %            ** Argument < 1
  1850.   \else %                        ** Argument >= 1
  1851.     \!logshift#2/%               ** Shift decimal pt as many places
  1852.     \!dimenE=#1.#2#3pt %         **   as there are figures in #2
  1853.   \fi %                          ** Now dimE holds revised X want log10 of
  1854.   \ifdim \!dimenE<\!rootten%          ** Transform X to XX between sqrt(10) 
  1855.     \multiply \!dimenE 10 %           **   and 10*sqrt(10)
  1856.     \advance  \!dimenF -1pt
  1857.   \fi
  1858.   \!dimenG=\!dimenE%                  ** dimG <- (XX + 10)
  1859.     \advance\!dimenG 10pt
  1860.   \advance\!dimenE -10pt %            ** dimE <- (XX - 10)
  1861.   \multiply\!dimenE 10 %              ** dimE = 10*(XX-10)
  1862.   \!divide\!dimenE\!dimenG\!dimenE%   ** Now dimE=10t==10*(XX-10)/(XX+10)
  1863.   \!removept\!dimenE\!t%              ** !t=10t, with "pt" removed
  1864.   \!dimenG=\!t\!dimenE%               ** dimG=100t**2
  1865.   \!removept\!dimenG\!tt%             ** !tt=100t**2, with "pt" removed
  1866.   \!dimenH=\!tt\!tenAe%               ** dimH=10*a5*(10t)**2 /100
  1867.     \divide\!dimenH 100
  1868.   \advance\!dimenH \!tenAc%           ** ditto + 10*a3
  1869.   \!dimenH=\!tt\!dimenH%              ** ditto * (10t)**2 /100
  1870.     \divide\!dimenH 100   
  1871.   \advance\!dimenH \!tenAa%           ** ditto + 10*a1
  1872.   \!dimenH=\!t\!dimenH%               ** ditto * 10t / 100
  1873.     \divide\!dimenH 100 %             ** Now dimH = log10(XX) - 1
  1874.   \advance\!dimenF \!dimenH}%         ** dimF = log10(X)
  1875. \def\!logshift#1{%
  1876.   \if #1/%
  1877.     \def\!next{\ignorespaces}%
  1878.   \else
  1879.     \advance\!dimenF 1pt 
  1880.     \def\!next{\!logshift}%
  1881.   \fi 
  1882.   \!next}
  1883.  \def\!!logshift#1{%
  1884.    \advance\!dimenF -1pt
  1885.    \if 0#1%
  1886.      \def\!next{\!!logshift}%
  1887.    \else
  1888.      \if p#1%
  1889.        \!dimenF=1pt
  1890.        \def\!next{\!dimenE=1p}%
  1891.      \else
  1892.        \def\!next{\!dimenE=#1.}%
  1893.      \fi
  1894.    \fi
  1895.    \!next}
  1896. % ***********************************************************
  1897. % *** PICTURES (Basic setups for PiCtures; \put commands) ***
  1898. % ***********************************************************
  1899. % **  User Commands:
  1900. % **    \beginpicture
  1901. % **    \endpicture    
  1902. % **    \endpicturesave <XREG,YREG>
  1903. % **    \setcoordinatesystem units <XUNIT,YUNIT> point at XREF YREF
  1904. % **    \put {OBJECT} [ORIENTATION] <XSHIFT,YSHIFT> at XCOORD YCOORD
  1905. % **    \multiput {OJBECT} [ORIENTATION] <XSHIFT,YSHIFT>) at
  1906. % **      XCOORD YCOORD
  1907. % **      *NUMBER_OF_TIMES DXCOORD DYCOORD  /
  1908. % **    \accountingon
  1909. % **    \accountingoff
  1910. % **    \stack [ORIENTATION] <LEADING> {LIST OF ITEMS}
  1911. % **    \lines [ORIENTATION] {LINES}
  1912. % **    \Lines [ORIENTATION] {LINES}
  1913. % **    \setdimensionmode
  1914. % **    \setcoordinatemode
  1915. % **    \Xdistance
  1916. % **    \Ydistance
  1917. % **  Internal commands:
  1918. % **    \!setputobject{OBJECT}{[ORIENTATION]<XSHIFT,YSHIFT>}
  1919. % **    \!dimenput{OBJECT}[ORIENTATION]<XSHIFT,YSHIFT>(XDIMEN,YDIMEN)
  1920. % **    \!setdimenmode
  1921. % **    \!setcoordmode
  1922. % **    \!ifdimenmode
  1923. % **    \!ifcoordmode
  1924. % **  \beginpicture
  1925. % **  \endpicture
  1926. % **  \endpicturesave <XREG,YREG>
  1927. % **    \beginpicture ... \endpicture  creates an hbox.  Objects are
  1928. % **    placed in this box using the \put command and the like (see below).
  1929. % **    The location of an object is specified in terms of coordinate system(s)
  1930. % **    established by \setcoordinatesystem.  Each coordinate system (there
  1931. % **    might be just one) specifies the length of 1 horizontal unit, the length
  1932. % **    of 1 vertical unit, and the coordinates of a "reference point".  The
  1933. % **    reference points of various coordinate systems will be in the same
  1934. % **    physical location.  The macros keep track of the size of the objects
  1935. % **    and their locations. The resulting hbox is the smallest hbox which
  1936. % **    encloses all the objects, and whose TEK reference point is the point
  1937. % **    on the left edge of the box closest vertically to the PICTEX reference
  1938. % **    point. Using \endpicturesave, you can (globally) save the distance TEK's
  1939. % **    reference point is to the right (respectively, up from) PICTEX's 
  1940. % **    reference point in the dimension register \XREG (respectively \YREG). 
  1941. % **    You can then \put the picture OBJECT into a larger picture so that its
  1942. % **    reference point is at (XCOORD,YCOORD) with the command
  1943. % **      \put {picture OBJECT} [Bl] <\XREG, \YREG> at  XCOORD YCOORD 
  1944. % **  \beginpicture : See Subsection 1.1 of the manual.
  1945. \def\beginpicture{%
  1946.   \setbox\!picbox=\hbox\bgroup%
  1947.   \!xleft=\maxdimen  
  1948.   \!xright=-\maxdimen
  1949.   \!ybot=\maxdimen
  1950.   \!ytop=-\maxdimen}
  1951. % **  \endpicture : See Subsection 1.1 of the manual.
  1952. \def\endpicture{%
  1953.   \ifdim\!xleft=\maxdimen%  ** check if nothing was put in picbox
  1954.     \!xleft=\!zpt \!xright=\!zpt \!ybot=\!zpt \!ytop=\!zpt 
  1955.   \fi
  1956.   \global\!Xleft=\!xleft \global\!Xright=\!xright
  1957.   \global\!Ybot=\!ybot \global\!Ytop=\!ytop
  1958.   \egroup%
  1959.   \ht\!picbox=\!Ytop  \dp\!picbox=-\!Ybot
  1960.   \ifdim\!Ybot>\!zpt
  1961.   \else 
  1962.     \ifdim\!Ytop<\!zpt
  1963.       \!Ybot=\!Ytop
  1964.     \else
  1965.       \!Ybot=\!zpt
  1966.     \fi
  1967.   \fi
  1968.   \hbox{\kern-\!Xleft\lower\!Ybot\box\!picbox\kern\!Xright}}
  1969. % **  \endpicturesave : See Subsection 8.4 of the manual.
  1970. \def\endpicturesave <#1,#2>{%
  1971.   \endpicture \global #1=\!Xleft \global #2=\!Ybot \ignorespaces}
  1972. % **   \setcoordinatesystem units <XUNIT,YUNIT> 
  1973. % **     point at XREF YREF  
  1974. % **   Each of `units <XUNIT,YUNIT>' and `point at XREF YREF' 
  1975. % **     are optional.
  1976. % **   Unit lengths must be given in dimensions (e.g., <10pt,1in>).
  1977. % **     Default unit lengths are 1pt, 1pt, or previous unit lengths.
  1978. % **   Reference point is specified in current units (e.g., 3 5 ). 
  1979. % **     Default reference point is 0 0 , or previous reference point.
  1980. % **   Unit lengths and reference points obey TEX's scoping rules.
  1981. % **   See Subsection 1.2 of the manual.
  1982. \def\setcoordinatesystem{%
  1983.   \!ifnextchar{u}{\!getlengths }
  1984.     {\!getlengths units <\!xunit,\!yunit>}}
  1985. \def\!getlengths units <#1,#2>{%
  1986.   \!xunit=#1\relax
  1987.   \!yunit=#2\relax
  1988.   \!ifcoordmode 
  1989.     \let\!SCnext=\!SCccheckforRP
  1990.   \else
  1991.     \let\!SCnext=\!SCdcheckforRP
  1992.   \fi
  1993.   \!SCnext}
  1994. \def\!SCccheckforRP{%
  1995.   \!ifnextchar{p}{\!cgetreference }
  1996.     {\!cgetreference point at {\!xref} {\!yref} }}
  1997. \def\!cgetreference point at #1 #2 {%
  1998.   \edef\!xref{#1}\edef\!yref{#2}%
  1999.   \!xorigin=\!xref\!xunit  \!yorigin=\!yref\!yunit  
  2000.   \!initinboundscheck % ** See linear.tex
  2001.   \ignorespaces}
  2002. \def\!SCdcheckforRP{%
  2003.   \!ifnextchar{p}{\!dgetreference}%
  2004.     {\ignorespaces}}
  2005. \def\!dgetreference point at #1 #2 {%
  2006.   \!xorigin=#1\relax  \!yorigin=#2\relax
  2007.   \ignorespaces}
  2008. %  ** \put {OBJECT} [XY] <XDIMEN,YDIMEN> at (XCOORD,YCOORD)
  2009. %  **   `[XY]' and `<XDIMEN,YDIMEN>' are optional.
  2010. %  **   First OBJECT is placed in an hbox (the "objectbox") and then a
  2011. %  **     "reference point" is assigned to the objectbox as follows:
  2012. %  **     [1] first, the reference point is taken to be the center of the box;
  2013. %  **     [2] next, centering is overridden by the specifications
  2014. %  **           X=l -- reference point along the left edge of the objectbox
  2015. %  **           X=r -- reference point along the right edge of the objectbox
  2016. %  **           Y=b -- reference point along the bottom edge of the objectbox
  2017. %  **           Y=B -- reference point along the Baseline of the objectbox
  2018. %  **           Y=t -- reference point along the top edge of the objectbox;
  2019. %  **     [3] finally the reference point is shifted left by XDIMEN, down
  2020. %  **           by YDIMEN  (both default to 0pt).
  2021. %  **   The objectbox is placed within PICBOX with its reference point at  
  2022. %  **     (XCOORD,YCOORD). 
  2023. %  **   If OBJECT is a saved box, say  box0, you have to write
  2024. %  **     \put{\box0}...   or  \put{\copy0}...
  2025. %  **   The objectbox is void after the put.
  2026. %  **   See Subsection 2.1 of the manual.
  2027. \long\def\put#1#2 at #3 #4 {%
  2028.   \!setputobject{#1}{#2}%
  2029.   \!xpos=\!M{#3}\!xunit  \!ypos=\!M{#4}\!yunit  
  2030.   \!rotateaboutpivot\!xpos\!ypos%
  2031.   \advance\!xpos -\!xorigin  \advance\!xpos -\!xshift
  2032.   \advance\!ypos -\!yorigin  \advance\!ypos -\!yshift
  2033.   \kern\!xpos\raise\!ypos\box\!putobject\kern-\!xpos%
  2034.   \!doaccounting\ignorespaces}
  2035. %  **   \multiput etc.  Like  \put.  The objectbox is not voided until the
  2036. %  **     termininating /, and is placed repeatedly with:
  2037. %  **     XCOORD YCOORD -- the objectbox is put down with its reference point
  2038. %  **       at (XCOORD,YCOORD);
  2039. %  **     *N DXCOORD DYCOORD -- each of N times the current
  2040. %  **       (xcoord,ycoord) is incremented by (DXCOORD,DYCOORD), and the
  2041. %  **       objectbox is put down with its reference point at (xcoord,ycoord)
  2042. %  **       (This specification has to follow an XCOORD YCOORD pair)
  2043. %  **     See Subsection 2.2 of the manual.
  2044. \long\def\multiput #1#2 at {%
  2045.   \!setputobject{#1}{#2}%
  2046.   \!ifnextchar"{\!putfromfile}{\!multiput}}
  2047. \def\!putfromfile"#1"{%
  2048.   \expandafter\!multiput \input #1 /}
  2049. \def\!multiput{%
  2050.   \futurelet\!nextchar\!!multiput}
  2051. \def\!!multiput{%
  2052.   \if *\!nextchar
  2053.     \def\!nextput{\!alsoby}%
  2054.   \else
  2055.     \if /\!nextchar
  2056.       \def\!nextput{\!finishmultiput}%
  2057.     \else
  2058.       \def\!nextput{\!alsoat}%
  2059.     \fi
  2060.   \fi
  2061.   \!nextput}
  2062. \def\!finishmultiput/{%
  2063.   \setbox\!putobject=\hbox{}%
  2064.   \ignorespaces}
  2065. %  **   \!alsoat XCOORD YCOORD 
  2066. %  **     The objectbox is put down with reference point at XCOORD,YCOORD
  2067. \def\!alsoat#1 #2 {%
  2068.   \!xpos=\!M{#1}\!xunit  \!ypos=\!M{#2}\!yunit  
  2069.   \!rotateaboutpivot\!xpos\!ypos%
  2070.   \advance\!xpos -\!xorigin  \advance\!xpos -\!xshift
  2071.   \advance\!ypos -\!yorigin  \advance\!ypos -\!yshift
  2072.   \kern\!xpos\raise\!ypos\copy\!putobject\kern-\!xpos%
  2073.   \!doaccounting
  2074.   \!multiput}
  2075. % **   \!alsoby*N DXCOORD DYCOORD
  2076. % **     N times, the current (XCOORD,YCOORD) is advanced by (DXCOORD,DYCOORD),
  2077. % **     and the current (shifted, oriented) OBJECT is put down.
  2078. \def\!alsoby*#1 #2 #3 {%
  2079.   \!dxpos=\!M{#2}\!xunit \!dypos=\!M{#3}\!yunit 
  2080.   \!rotateonly\!dxpos\!dypos
  2081.   \!ntemp=#1%
  2082.   \!!loop\ifnum\!ntemp>0
  2083.     \advance\!xpos by \!dxpos  \advance\!ypos by \!dypos
  2084.     \kern\!xpos\raise\!ypos\copy\!putobject\kern-\!xpos%
  2085.     \advance\!ntemp by -1
  2086.   \repeat
  2087.   \!doaccounting 
  2088.   \!multiput}
  2089. % **  \accountingoff : Suspends PiCTeX's accounting of the aggregate
  2090. % **    size of the picture box.
  2091. % **  \accounting on : Reinstates accounting.
  2092. % **  See Subsection 8.2 of the manual.
  2093. \def\accountingon{\def\!doaccounting{\!!doaccounting}\ignorespaces}
  2094. \def\accountingoff{\def\!doaccounting{}\ignorespaces}
  2095. \accountingon
  2096. \def\!!doaccounting{%
  2097.   \!xtemp=\!xpos  
  2098.   \!ytemp=\!ypos
  2099.   \ifdim\!xtemp<\!xleft 
  2100.      \!xleft=\!xtemp 
  2101.   \fi
  2102.   \advance\!xtemp by  \!wd 
  2103.   \ifdim\!xright<\!xtemp 
  2104.     \!xright=\!xtemp
  2105.   \fi
  2106.   \advance\!ytemp by -\!dp
  2107.   \ifdim\!ytemp<\!ybot  
  2108.     \!ybot=\!ytemp
  2109.   \fi
  2110.   \advance\!ytemp by  \!dp
  2111.   \advance\!ytemp by  \!ht 
  2112.   \ifdim\!ytemp>\!ytop  
  2113.     \!ytop=\!ytemp  
  2114.   \fi}
  2115. \long\def\!setputobject#1#2{%
  2116.   \setbox\!putobject=\hbox{#1}%
  2117.   \!ht=\ht\!putobject  \!dp=\dp\!putobject  \!wd=\wd\!putobject
  2118.   \wd\!putobject=\!zpt
  2119.   \!xshift=.5\!wd   \!yshift=.5\!ht   \advance\!yshift by -.5\!dp
  2120.   \edef\!putorientation{#2}%
  2121.   \expandafter\!SPOreadA\!putorientation[]\!nil%
  2122.   \expandafter\!SPOreadB\!putorientation<\!zpt,\!zpt>\!nil\ignorespaces}
  2123. \def\!SPOreadA#1[#2]#3\!nil{\!etfor\!orientation:=#2\do\!SPOreviseshift}
  2124. \def\!SPOreadB#1<#2,#3>#4\!nil{\advance\!xshift by -#2\advance\!yshift by -#3}
  2125. \def\!SPOreviseshift{%
  2126.   \if l\!orientation 
  2127.     \!xshift=\!zpt
  2128.   \else 
  2129.     \if r\!orientation 
  2130.       \!xshift=\!wd
  2131.     \else 
  2132.       \if b\!orientation
  2133.         \!yshift=-\!dp
  2134.       \else 
  2135.         \if B\!orientation 
  2136.           \!yshift=\!zpt
  2137.         \else 
  2138.           \if t\!orientation 
  2139.             \!yshift=\!ht
  2140.           \fi 
  2141.         \fi
  2142.       \fi
  2143.     \fi
  2144.   \fi}
  2145. %  **  \!dimenput{OBJECT} <XDIMEN,YDIMEN> [XY] (XLOC,YLOC)
  2146. %  **    This is an internal put routine, similar to \put, except that
  2147. %  **    XLOC=distance right from reference point, YLOC=distance up from
  2148. %  **    reference point. XLOC and YLOC are dimensions, so this routine
  2149. %  **    is completely independent of the current coordinate system. 
  2150. %  **    This routine does NOT do ROTATIONS.
  2151. \long\def\!dimenput#1#2(#3,#4){%
  2152.   \!setputobject{#1}{#2}%
  2153.   \!xpos=#3\advance\!xpos by -\!xshift
  2154.   \!ypos=#4\advance\!ypos by -\!yshift
  2155.   \kern\!xpos\raise\!ypos\box\!putobject\kern-\!xpos%
  2156.   \!doaccounting\ignorespaces}
  2157. %  ** The following macros permit the picture drawing routines to be used 
  2158. %  ** either in the default "coordinate mode", or in "dimension mode".
  2159. %  **   In coordinate mode  \!M(1.5,\!xunit)    expands to  1.5\!xunit
  2160. %  **   In dimension  mode  \!M(1.5pt,\!xunit)  expands to  1.5pt
  2161. %  ** Dimension mode is useful in coding macros.
  2162. %  ** Any special purpose picture macro that sets dimension mode should 
  2163. %  ** reset coordinate mode before completion.
  2164. %  ** See Subsection 9.2 of the manual.
  2165. \def\!setdimenmode{%
  2166.   \let\!M=\!M!!\ignorespaces}
  2167. \def\!setcoordmode{%
  2168.   \let\!M=\!M!\ignorespaces}
  2169. \def\!ifcoordmode{%
  2170.   \ifx \!M \!M!}
  2171. \def\!ifdimenmode{%
  2172.   \ifx \!M \!M!!}
  2173. \def\!M!#1#2{#1#2} 
  2174. \def\!M!!#1#2{#1}
  2175. \!setcoordmode
  2176. \let\setdimensionmode=\!setdimenmode
  2177. \let\setcoordinatemode=\!setcoordmode
  2178. %  ** \Xdistance{XCOORD}, \Ydistance{YCOORD}  are the horizontal and
  2179. %  **   vertical distances from the origin (0,0) to the point
  2180. %  **   (XCOORD,YCOORD)  in the current coordinate system.
  2181. %  ** See Subsection 9.2 of the manual.
  2182. \def\Xdistance#1{%
  2183.   \!M{#1}\!xunit
  2184.   \ignorespaces}
  2185. \def\Ydistance#1{%
  2186.   \!M{#1}\!yunit
  2187.   \ignorespaces}
  2188. % ** The following macros -- \stack, \line, and \Lines -- are useful for
  2189. % **   annotating PiCtures. They can be used outside the \beginpicture ...
  2190. % **   \endpicture environment.
  2191. % ** \stack [POSITIONING] <LEADING> {VALUESLIST}
  2192. % ** Builds a vertical stack of the values in VALUESLIST. Values in
  2193. % ** VALUESLIST are separated by commas.  In the resulting stack, values are
  2194. % ** centered by default, and positioned flush left (right) if 
  2195. % ** POSITIONING = l (r).  Values are separated vertically by LEADING,
  2196. % ** which defaults to \stackleading.
  2197. % ** See Subsection 2.3 of the manual.
  2198. \def\stack{%
  2199.   \!ifnextchar[{\!stack}{\!stack[c]}}
  2200. \def\!stack[#1]{%
  2201.   \let\!lglue=\hfill \let\!rglue=\hfill
  2202.   \expandafter\let\csname !#1glue\endcsname=\relax
  2203.   \!ifnextchar<{\!!stack}{\!!stack<\stackleading>}}
  2204. \def\!!stack<#1>#2{%
  2205.   \vbox{\def\!valueslist{}\!ecfor\!value:=#2\do{%
  2206.     \expandafter\!rightappend\!value\withCS{\\}\to\!valueslist}%
  2207.     \!lop\!valueslist\to\!value
  2208.     \let\\=\cr\lineskiplimit=\maxdimen\lineskip=#1%
  2209.     \baselineskip=-1000pt\halign{\!lglue##\!rglue\cr \!value\!valueslist\cr}}%
  2210.   \ignorespaces}
  2211. % ** \lines [POSITIONING] {LINES}
  2212. % ** Builds a vertical array of the lines in LINES. Each line in LINES
  2213. % ** is terminated by a \cr.  In the resulting array, lines are
  2214. % ** centered by default, and positioned flush left (right) if 
  2215. % ** POSITIONING = l (r).  The lines in the array are subject to TeX's
  2216. % ** usual spacing rules: in particular the baselines are ordinarily an equal
  2217. % ** distance apart. The baseline of the array is the baseline of the
  2218. % ** the bottom line.
  2219. % ** See Subsection 2.3 of the manual.
  2220. \def\lines{%
  2221.   \!ifnextchar[{\!lines}{\!lines[c]}}
  2222. \def\!lines[#1]#2{%
  2223.   \let\!lglue=\hfill \let\!rglue=\hfill
  2224.   \expandafter\let\csname !#1glue\endcsname=\relax
  2225.   \vbox{\halign{\!lglue##\!rglue\cr #2\crcr}}%
  2226.   \ignorespaces}
  2227. % ** \Lines [POSITIONING] {LINES}
  2228. % ** Like \lines, but the baseline of the array is the baseline of the
  2229. % ** top line.  See Subsection 2.3 of the manual.
  2230. \def\Lines{%
  2231.   \!ifnextchar[{\!Lines}{\!Lines[c]}}
  2232. \def\!Lines[#1]#2{%
  2233.   \let\!lglue=\hfill \let\!rglue=\hfill
  2234.   \expandafter\let\csname !#1glue\endcsname=\relax
  2235.   \vtop{\halign{\!lglue##\!rglue\cr #2\crcr}}%
  2236.   \ignorespaces}
  2237. % *********************************************
  2238. % *** PLOTTING (Things to do with plotting) ***
  2239. % *********************************************
  2240. % **  User commands
  2241. % **    \setplotsymbol ({PLOTSYMBOL} [ORIENTATION] <XSHIFT,YSHIFT>)
  2242. % **    \savelinesandcurves on "FILE_NAME"
  2243. % **    \dontsavelinesandcurves
  2244. % **    \writesavefile {MESSAGE}
  2245. % **    \replot {FILE_NAME}
  2246. % **  Internal command
  2247. % **    \!plot(XDIMEN,YDIMEN)
  2248. % **  \setplotsymbol ({PLOTSYMBOL} [ ] < , >)
  2249. % **  Save PLOTSYMBOL away in an hbox for use with curve plotting routines
  2250. % **  See Subsection 5.2 of the manual.
  2251. \def\setplotsymbol(#1#2){%
  2252.   \!setputobject{#1}{#2}
  2253.   \setbox\!plotsymbol=\box\!putobject%
  2254.   \!plotsymbolxshift=\!xshift 
  2255.   \!plotsymbolyshift=\!yshift 
  2256.   \ignorespaces}
  2257. \setplotsymbol({\fiverm .})%       ** initialize plotsymbol
  2258. % **  \!plot is either \!!plot (when no lines and curves are being saved) or
  2259. % **                   \!!!plot (when   lines and curves are being saved)
  2260. % **  \!!plot(XDIMEN,YDIMEN)
  2261. % **  Places the current plotsymbol a horizontal distance=XDIMEN-xorigin 
  2262. % **    and a vertical distance=YDIMEN-yorigin from the current
  2263. % **    reference point.  
  2264. \def\!!plot(#1,#2){%
  2265.   \!dimenA=-\!plotxorigin \advance \!dimenA by #1%    ** over
  2266.   \!dimenB=-\!plotyorigin \advance \!dimenB by #2%    ** up
  2267.   \kern\!dimenA\raise\!dimenB\copy\!plotsymbol\kern-\!dimenA%
  2268.   \ignorespaces}
  2269. % **  \!!!plot(XDIMEN,YDIMEN)
  2270. % **  Like \!!plot, but also saves the plot location in units of 
  2271. % **    scaled point, on file `replotfile'
  2272. \def\!!!plot(#1,#2){%
  2273.   \!dimenA=-\!plotxorigin \advance \!dimenA by #1%    ** over
  2274.   \!dimenB=-\!plotyorigin \advance \!dimenB by #2%    ** up
  2275.   \kern\!dimenA\raise\!dimenB\copy\!plotsymbol\kern-\!dimenA%
  2276.   \!countE=\!dimenA
  2277.   \!countF=\!dimenB
  2278.   \immediate\write\!replotfile{\the\!countE,\the\!countF.}%
  2279.   \ignorespaces}
  2280. % ** \savelinesandcurves on "FILE_NAME"
  2281. % **   Switch to save locations used for plotting lines and curves
  2282. % **   (No advantage in saving locations for solid lines; however
  2283. % **   replotting curve locations speeds things up by a factor of about 4. 
  2284. % ** \dontsavelinesandcurves
  2285. % **   Terminates \savelinesandcurves. The default.
  2286. % ** See Subsection 5.6 of the manual.
  2287. \def\savelinesandcurves on "#1" {%
  2288.   \immediate\closeout\!replotfile
  2289.   \immediate\openout\!replotfile=#1%
  2290.   \let\!plot=\!!!plot}
  2291. \def\dontsavelinesandcurves {%
  2292.   \let\!plot=\!!plot}
  2293. \dontsavelinesandcurves
  2294. % ** \writesavefile {MESSAGE}
  2295. % ** The message is preceded by a "%", so that it won't interfere
  2296. % ** with replotting.
  2297. % ** See Subsection 5.6 of the manual.
  2298. {\catcode`\%=11\xdef\!Commentsignal{%}}
  2299. \def\writesavefile#1 {%
  2300.   \immediate\write\!replotfile{\!Commentsignal #1}%
  2301.   \ignorespaces}
  2302. % ** \replot "FILE_NAME"
  2303. % **   Replots the locations saved earlier under \savelinesandcurves
  2304. % **   on "FILE_NAME"
  2305. % ** See Subsection 5.6 of the manual.
  2306. \def\replot"#1" {%
  2307.   \expandafter\!replot\input #1 /}
  2308. \def\!replot#1,#2. {%
  2309.   \!dimenA=#1sp
  2310.   \kern\!dimenA\raise#2sp\copy\!plotsymbol\kern-\!dimenA
  2311.   \futurelet\!nextchar\!!replot}
  2312. \def\!!replot{%
  2313.   \if /\!nextchar 
  2314.     \def\!next{\!finish}%
  2315.   \else
  2316.     \def\!next{\!replot}%
  2317.   \fi
  2318.   \!next}
  2319. % **************************************************
  2320. % ***  PYTHAGORAS  (Euclidean distance function) ***
  2321. % **************************************************
  2322. % ** User command:
  2323. % **   \placehypotenuse for <dimension1> and <dimension2> in <register> 
  2324. % ** Internal command:
  2325. % **   \!Pythag{X}{Y}{Z}
  2326. % **     Input X,Y are dimensions, or dimension registers.
  2327. % **     Output Z == sqrt(X**2+Y**2) must be a dimension register.
  2328. % **     Assumes that |X|+|Y| < 2048pt (about 28in).
  2329. % ** Without loss of generality, suppose  x>0, y>0.  Put s = x+y,
  2330. % **   z = sqrt(x**2+y**2). Then  z = s*f,  where  f = sqrt(t**2 + (1-t)**2)
  2331. % **   = sqrt((1+tau**2)/2), where  t = x/s  and  tau = 2(t-1/2) .
  2332. % ** Uses the \!divide macro (which uses registers \!dimenA--\!dimenD.
  2333. % ** Uses the \!removept macro   (e.g., 123.45pt --> 123.45)
  2334. % ** Uses registers \!dimenE--\!dimenI.
  2335. \def\!Pythag#1#2#3{%
  2336.   \!dimenE=#1\relax                                     
  2337.   \ifdim\!dimenE<\!zpt 
  2338.     \!dimenE=-\!dimenE 
  2339.   \fi%                                            ** dimE = |x|
  2340.   \!dimenF=#2\relax
  2341.   \ifdim\!dimenF<\!zpt 
  2342.     \!dimenF=-\!dimenF 
  2343.   \fi%                                            ** dimF = |y|
  2344.   \advance \!dimenF by \!dimenE%                  ** dimF = s = |x|+|y|
  2345.   \ifdim\!dimenF=\!zpt 
  2346.     \!dimenG=\!zpt%                               ** dimG = z = sqrt(x**2+y**2)
  2347.   \else 
  2348.     \!divide{8\!dimenE}\!dimenF\!dimenE%          ** now dimE = 8t = (8|x|)/s
  2349.     \advance\!dimenE by -4pt%                     ** 8tau = (8t-4)*2
  2350.       \!dimenE=2\!dimenE%                         **   (tau = 2*t - 1)
  2351.     \!removept\!dimenE\!!t%                       ** 8tau, without "pt"
  2352.     \!dimenE=\!!t\!dimenE%                        ** (8tau)**2, in pts
  2353.     \advance\!dimenE by 64pt%                     ** u = [64 + (8tau)**2]/2
  2354.     \divide \!dimenE by 2%                        **   [u = (8f)**2]
  2355.     \!dimenH=7pt%                                 ** initial guess g at sqrt(u)
  2356.     \!!Pythag\!!Pythag\!!Pythag%                  ** 3 iterations give sqrt(u)
  2357.     \!removept\!dimenH\!!t%                       ** 8f=sqrt(u), without "pt"
  2358.     \!dimenG=\!!t\!dimenF%                        ** z = (8f)*s/8
  2359.     \divide\!dimenG by 8
  2360.   \fi
  2361.   #3=\!dimenG
  2362.   \ignorespaces}
  2363. \def\!!Pythag{%                                   ** Newton-Raphson for sqrt
  2364.   \!divide\!dimenE\!dimenH\!dimenI%               ** v = u/g
  2365.   \advance\!dimenH by \!dimenI%                   ** g <-- (g + u/g)/2
  2366.     \divide\!dimenH by 2}
  2367. % **  \placehypotenuse for <XI> and <ETA> in <ZETA>
  2368. % **  See Subsection 9.3 of the manual.
  2369. \def\placehypotenuse for <#1> and <#2> in <#3> {%
  2370.   \!Pythag{#1}{#2}{#3}}
  2371. % **********************************************
  2372. % *** QUADRATIC ARC  (Draws a quadratic arc) ***
  2373. % **********************************************
  2374. % **  Internal command
  2375. % **    \!qjoin (XCOORD1,YCOORD1) (XCOORD2,YCOORD2)
  2376. % **  \!qjoin (XCOORD1,YCOORD1) (XCOORD2,YCOORD2)
  2377. % **  Draws an arc starting at the (last) point specified by the most recent
  2378. % **  \!qjoin, or \!ljoin, or \!start  and passing through (X_1,Y_1), (X_2,Y_2).
  2379. % **  Uses quadratic interpolation in both  x  and  y:  
  2380. % **    x(t), 0 <= t <= 1, interpolates  x_0, x_1, x_2  at  t=0, .5, 1
  2381. % **    y(t), 0 <= t <= 1, interpolates  y_0, y_1, y_2  at  t=0, .5, 1
  2382. \def\!qjoin (#1,#2) (#3,#4){%
  2383.   \advance\!intervalno by 1
  2384.   \!ifcoordmode
  2385.     \edef\!xmidpt{#1}\edef\!ymidpt{#2}%
  2386.   \else
  2387.     \!dimenA=#1\relax \edef\!xmidpt{\the\!dimenA}%
  2388.     \!dimenA=#2\relax \edef\!xmidpt{\the\!dimenA}%
  2389.   \fi
  2390.   \!xM=\!M{#1}\!xunit  \!yM=\!M{#2}\!yunit   \!rotateaboutpivot\!xM\!yM
  2391.   \!xE=\!M{#3}\!xunit  \!yE=\!M{#4}\!yunit   \!rotateaboutpivot\!xE\!yE
  2392. % ** Find coefficients for x(t)=a_x + b_x*t + c_x*t**2
  2393.   \!dimenA=\!xM  \advance \!dimenA by -\!xS%   ** dimA = I = xM - xS
  2394.   \!dimenB=\!xE  \advance \!dimenB by -\!xM%   ** dimB = II = xE-xM
  2395.   \!xB=3\!dimenA \advance \!xB by -\!dimenB%   ** b=3I-II
  2396.   \!xC=2\!dimenB \advance \!xC by -2\!dimenA%  ** c=2(II-I)
  2397. % ** Find coefficients for y(t)=y_x + b_y*t + c_y*t**2
  2398.   \!dimenA=\!yM  \advance \!dimenA by -\!yS%   
  2399.   \!dimenB=\!yE  \advance \!dimenB by -\!yM%  
  2400.   \!yB=3\!dimenA \advance \!yB by -\!dimenB%  
  2401.   \!yC=2\!dimenB \advance \!yC by -2\!dimenA% 
  2402. % ** Use Simpson's rule to calculate arc length over [0,1/2]:
  2403. % **   arc length = 1/2[1/6 f(0) + 4/6 f(1/4) + 1/6 f(1/2)]
  2404. % ** with f(t) = sqrt(x'(t)**2 + y'(t)**2).
  2405.   \!xprime=\!xB  \!yprime=\!yB%          ** x'(t) = b + 2ct
  2406.   \!dxprime=.5\!xC  \!dyprime=.5\!yC%    ** dt=1/4 ==> dx'(t) = c/2
  2407.   \!getf \!midarclength=\!dimenA
  2408.   \!getf \advance \!midarclength by 4\!dimenA
  2409.   \!getf \advance \!midarclength by \!dimenA
  2410.   \divide \!midarclength by 12
  2411. % ** Get arc length over [0,1].
  2412.   \!arclength=\!dimenA
  2413.   \!getf \advance \!arclength by 4\!dimenA
  2414.   \!getf \advance \!arclength by \!dimenA
  2415.   \divide \!arclength by 12%             ** Now have arc length over [1/2,1]
  2416.   \advance \!arclength by \!midarclength
  2417.   \global\advance \totalarclength by \!arclength
  2418. % ** Check to see if there's anything to plot in this interval
  2419.   \ifdim\!distacross>\!arclength 
  2420.     \advance \!distacross by -\!arclength%   ** nothing 
  2421.   \else
  2422.     \!initinverseinterp%  ** initialize for inverse interpolation on arc length
  2423.     \loop\ifdim\!distacross<\!arclength%     ** loop over points on arc 
  2424.       \!inverseinterp%    ** find  t  such that arc length[0,t] = distacross,
  2425. %                         **   using inverse quadratic interpolation
  2426. %                         ** now evaluate x(t)=(c*t + b)*t + a
  2427.       \!xpos=\!t\!xC \advance\!xpos by \!xB
  2428.         \!xpos=\!t\!xpos \advance \!xpos by \!xS
  2429. %                                             ** evaluate y(t)
  2430.       \!ypos=\!t\!yC \advance\!ypos by \!yB
  2431.         \!ypos=\!t\!ypos \advance \!ypos by \!yS
  2432.       \!plotifinbounds%                       ** plot point if in bounds
  2433.       \advance\!distacross \plotsymbolspacing%** advance arc length for next pt
  2434.       \!advancedashing%                       ** see "linear"
  2435.     \repeat  
  2436.     \advance \!distacross by -\!arclength%    ** prepare for next interval 
  2437.   \fi
  2438.   \!xS=\!xE%              ** shift ending points to starting points
  2439.   \!yS=\!yE
  2440.   \ignorespaces}
  2441. % ** \!getf -- Calculates sqrt(x'(t)**2 + y'(t)**2) and advances
  2442. % **   x'(t) and y'(t)
  2443. \def\!getf{\!Pythag\!xprime\!yprime\!dimenA%
  2444.   \advance\!xprime by \!dxprime
  2445.   \advance\!yprime by \!dyprime}
  2446. % ** \!initinverseinterp -- initializes for inverse quadratic interpolation
  2447. % ** of arc length provided  1/3 < midarclength/arclength < 2/3; otherwise
  2448. % ** initializes for inverse linear interpolation.
  2449. \def\!initinverseinterp{%
  2450.   \ifdim\!arclength>\!zpt
  2451.     \!divide{8\!midarclength}\!arclength\!dimenE% ** dimE=8w=8r/s, where  r 
  2452. %                                               **  = midarclength, s=arclength
  2453. % **  Test for  w  out of range:  w<1/3  or w>2/3
  2454.     \ifdim\!dimenE<\!wmin \!setinverselinear
  2455.     \else 
  2456.       \ifdim\!dimenE>\!wmax \!setinverselinear
  2457.       \else%                                    ** w  in range: initialize
  2458.         \def\!inverseinterp{\!inversequad}\ignorespaces
  2459. % **     Calculate the coefficients  \!beta  and  \!gamma  of the quadratic
  2460. % **                    t = \!beta*v + \!gamma*v**2
  2461. % **     taking the values  t=0, 1/2, 1  at  v=0, w==r/s, 1  respectively:
  2462. % **        \!beta = (1/2 - w**2)/[w(1-w)] 
  2463. % **        \!gamma = 1 - beta.
  2464.          \!removept\!dimenE\!Ew%           **  8w, without "pt"
  2465.          \!dimenF=-\!Ew\!dimenE%           **  -(8w)**2
  2466.          \advance\!dimenF by 32pt%         **  32 - (8w)**2
  2467.          \!dimenG=8pt 
  2468.          \advance\!dimenG by -\!dimenE%    **  8 - 8w
  2469.          \!dimenG=\!Ew\!dimenG%            **  (8w)*(8-8w)
  2470.          \!divide\!dimenF\!dimenG\!beta%   **  beta = (32-(8w)**2)/(8w(8-8w))
  2471. %                                          **       = (1/2 - w**2)/(w(1-w))
  2472.          \!gamma=1pt
  2473.          \advance \!gamma by -\!beta%      **  gamma = 1-beta
  2474.       \fi%       ** end of the \ifdim\!dimenE>\!wmax
  2475.     \fi%         ** end of the \ifdim\!dimenE<\!wmin
  2476.   \fi%           ** end of the \ifdim\!arclength>\!zpt
  2477.   \ignorespaces}
  2478. % ** For 0 <= t <= 1, let AL(t) = arclength[0,t]/arclength[0,1]; note
  2479. % ** AL(0)=0, AL(1/2)=midarclength/arclength, AL(1)=1.  This routine
  2480. % ** calculates an approximation to AL^{-1}(distance across/arclength),
  2481. % ** using the assumption that AL^{-1} is quadratic.  Specifically, 
  2482. % ** it finds  t  such that
  2483. % **    AL^{-1}(v) =. t = v*(\!beta + \!gamma*v)
  2484. % ** where  \!beta  and  \!gamma  are set by \!initinv, and where
  2485. % ** v=distance across/arclength
  2486. \def\!inversequad{%
  2487.   \!divide\!distacross\!arclength\!dimenG%   ** dimG = v = distacross/arclength
  2488.   \!removept\!dimenG\!v%                     ** v, without "pt"
  2489.   \!dimenG=\!v\!gamma%                       ** gamma*v
  2490.   \advance\!dimenG by \!beta%                ** beta + gamma*v
  2491.   \!dimenG=\!v\!dimenG%                      ** t = v*(beta + gamma*v)
  2492.   \!removept\!dimenG\!t}%                    ** t, without "pt"
  2493. % ** When  w <= 1/3  or  w >= 2/3, the following routine writes (using
  2494. % ** plain TEK's \wlog command) a warning message on the user's log file,
  2495. % ** and initializes for inverse linear interpolation on arc length.
  2496. \def\!setinverselinear{%
  2497.   \def\!inverseinterp{\!inverselinear}%
  2498.   \divide\!dimenE by 8 \!removept\!dimenE\!t
  2499.   \!countC=\!intervalno \multiply \!countC 2
  2500.   \!countB=\!countC     \advance \!countB -1
  2501.   \!countA=\!countB     \advance \!countA -1
  2502.   \wlog{\the\!countB th point (\!xmidpt,\!ymidpt) being plotted 
  2503.     doesn't lie in the}%
  2504.   \wlog{ middle third of the arc between the \the\!countA th 
  2505.     and \the\!countC th points:}%
  2506.   \wlog{ [arc length \the\!countA\space to \the\!countB]/[arc length 
  2507.     \the \!countA\space to \the\!countC]=\!t.}%
  2508.   \ignorespaces}
  2509. % **  Inverse linear interpolation
  2510. \def\!inverselinear{% 
  2511.   \!divide\!distacross\!arclength\!dimenG
  2512.   \!removept\!dimenG\!t}
  2513. % **************************************
  2514. % **  ROTATIONS  (Handles rotations) ***
  2515. % **************************************
  2516. % ** User commands
  2517. % **   \startrotation [by COS_OF_ANGLE SIN_OF_ANGLE] [about XPIVOT YPIVOT]
  2518. % **   \stoprotation
  2519. % **   \startrotation [by COS_OF_ANGLE SIN_OF_ANGLE] [about XPIVOT YPIVOT]
  2520. % ** Future (XCOORD,YCOORD)'s will be rotated about (XPIVOT,YPIVOT) 
  2521. % ** by the angle with the give COS and SIN. Both fields are optional.
  2522. % ** [COS,SIN] defaults to previous value, or (1,0).
  2523. % ** (XPIVOT,YPIVOT) defaults to previous value, or (0,0)
  2524. % ** You can't change the coordinate system in the scope of a rotation.
  2525. % ** See Subsection 9.1 of the manual.
  2526. \def\startrotation{%
  2527.   \let\!rotateaboutpivot=\!!rotateaboutpivot
  2528.   \let\!rotateonly=\!!rotateonly
  2529.   \!ifnextchar{b}{\!getsincos }%
  2530.     {\!getsincos by {\!cosrotationangle} {\!sinrotationangle} }}
  2531. \def\!getsincos by #1 #2 {%
  2532.   \edef\!cosrotationangle{#1}%
  2533.   \edef\!sinrotationangle{#2}%
  2534.   \!ifcoordmode 
  2535.     \let\!ROnext=\!ccheckforpivot
  2536.   \else
  2537.     \let\!ROnext=\!dcheckforpivot
  2538.   \fi
  2539.   \!ROnext}
  2540. \def\!ccheckforpivot{%
  2541.   \!ifnextchar{a}{\!cgetpivot}%
  2542.     {\!cgetpivot about {\!xpivotcoord} {\!ypivotcoord} }}
  2543. \def\!cgetpivot about #1 #2 {%
  2544.   \edef\!xpivotcoord{#1}%
  2545.   \edef\!ypivotcoord{#2}%
  2546.   \!xpivot=#1\!xunit  \!ypivot=#2\!yunit
  2547.   \ignorespaces}
  2548. \def\!dcheckforpivot{%
  2549.   \!ifnextchar{a}{\!dgetpivot}{\ignorespaces}}
  2550. \def\!dgetpivot about #1 #2 {%
  2551.   \!xpivot=#1\relax  \!ypivot=#2\relax
  2552.   \ignorespaces}
  2553. % ** Following terminates rotation.
  2554. % ** See Subsection 9.1 of the manual.
  2555. \def\stoprotation{%
  2556.   \let\!rotateaboutpivot=\!!!rotateaboutpivot
  2557.   \let\!rotateonly=\!!!rotateonly
  2558.   \ignorespaces}
  2559. % ** !!rotateaboutpivot{XREG}{YREG}
  2560. % ** XREG <-- xpvt + cos(angle)*(XREG-xpvt) - sin(angle)*(YREG-ypvt)
  2561. % ** YREG <-- ypvt + cos(angle)*(YREG-ypvt) + sin(angle)*(XREG-xpvt)
  2562. % ** XREG,YREG are dimension registers. Can't be \!dimenA to \!dimenD
  2563. \def\!!rotateaboutpivot#1#2{%
  2564.   \!dimenA=#1\relax  \advance\!dimenA -\!xpivot
  2565.   \!dimenB=#2\relax  \advance\!dimenB -\!ypivot
  2566.   \!dimenC=\!cosrotationangle\!dimenA
  2567.     \advance \!dimenC -\!sinrotationangle\!dimenB
  2568.   \!dimenD=\!cosrotationangle\!dimenB
  2569.     \advance \!dimenD  \!sinrotationangle\!dimenA
  2570.   \advance\!dimenC \!xpivot  \advance\!dimenD \!ypivot
  2571.   #1=\!dimenC  #2=\!dimenD
  2572.   \ignorespaces}
  2573. % ** \!!rotateonly{XREG}{YREG}
  2574. % ** Like \!!rotateaboutpivot, but with a pivot of  (0,0)
  2575. \def\!!rotateonly#1#2{%
  2576.   \!dimenA=#1\relax  \!dimenB=#2\relax 
  2577.   \!dimenC=\!cosrotationangle\!dimenA
  2578.     \advance \!dimenC -\!rotsign\!sinrotationangle\!dimenB
  2579.   \!dimenD=\!cosrotationangle\!dimenB
  2580.     \advance \!dimenD  \!rotsign\!sinrotationangle\!dimenA
  2581.   #1=\!dimenC  #2=\!dimenD
  2582.   \ignorespaces}
  2583. \def\!rotsign{}
  2584. \def\!!!rotateaboutpivot#1#2{\relax}
  2585. \def\!!!rotateonly#1#2{\relax}
  2586. \stoprotation
  2587. \def\!reverserotateonly#1#2{%
  2588.   \def\!rotsign{-}%
  2589.   \!rotateonly{#1}{#2}%
  2590.   \def\!rotsign{}%
  2591.   \ignorespaces}
  2592. % **********************************
  2593. % *** SHADING  (Handles shading) ***
  2594. % **********************************
  2595. % **  User commands
  2596. % **    \setshadegrid [span <SPAN>] [point at XSHADE YSHADE] 
  2597. % **    \setshadesymbol [<LS, RS, BS, TS>] ({SHADESYMBOL}
  2598. % **      <XDIMEN,YDIMEN> [ORIENTATION])
  2599. % **  Internal commands:
  2600. % **    \!startvshade  (xS,ybS,ytS)
  2601. % **    \!starthshade  (yS,xlS,xrS)
  2602. % **    \!lshade [<LS,RS,BS,TS>]
  2603. % **       ** when shading vertically:
  2604. % **       [the region from (xS,ybS,ytS) to] (xE,ybE,ytE)
  2605. % **       ** when shading horizontally:
  2606. % **       [the region from (yS,xlS,xrS) to] (yE,xlE,xrE)
  2607. % **    \!qshade [<LS,RS,BS,TS>]
  2608. % **       ** when shading vertically:
  2609. % **       [the region from (xS,ybS,ytS) to] (xM,ybM,ytM)  (xE,ybE,ytE)
  2610. % **       ** when shading horizontally:
  2611. % **       [the region from (yS,xlS,xrS) to] (yM,xlM,xrM)  (yE,xlE,xrE)
  2612. % **    \!lattice{ANCHOR}{SPAN}{LOCATION}{INDEX}{LATTICE LOCATION}
  2613. % **    \!override{NOMINAL DIMEN}{REPLACEMENT DIMEN}{DIMEN}
  2614. % **  The shading routine can operate either in a "vertical mode" or a
  2615. % **  "horizontal mode".  In vertical mode, the region to be shaded is specified
  2616. % **  in the form
  2617. % **                 {(x,y): xl <= x <= xr  &  yb(x) <= y <= yt(x)}
  2618. % **  where  yb  and  yt  are functions of  x.  In horizontal mode, the region
  2619. % **  is specified in the form
  2620. % **                 {(x,y): yb <= y <= yt  &  xl(y) <= x <= xr(y)}.
  2621. % **  The functions  yb  and  yt  may be either both linear or both quadratic;
  2622. % **  similarly for  xl  and  xr.  A region with say, piecewise quadratic bottom
  2623. % **  and top boundaries, can be shaded by consecutive (vertical) \!qshades,
  2624. % **  proceeding from left to right.  Similarly, a region with piecewise     
  2625. % **  quadratic left and right boundaries can be shaded by consecutive
  2626. % **  (horizontal) \!qshades, proceeding from bottom to top.  More complex
  2627. % **  regions can be shaded by partitioning them into appropriate subregions,
  2628. % **  and shading those.
  2629. % **  Shading is accomplished by placing a user-selected shading symbol at
  2630. % **  those points of a regular grid which fall within the region to be
  2631. % **  shaded.  This region can be "shrunk" so that a largish shading symbol
  2632. % **  will not extend outside it.  Shrinking is accomplished by specifying
  2633. % **  shrinkages for the left, right, bottom, and top boundaries, in a manner
  2634. % **  discussed further below.
  2635. % **  \shades and \!joins MUST NOT be intermingled.  Finish drawing a curve
  2636. % **  before starting to shade a region, and finish shading a region before
  2637. % **  starting to draw a curve.
  2638. % **  \setshadegrid [span <SPAN>] [point at XSHADE YSHADE] 
  2639. % **  The shading symbol is placed down on the points of a grid centered
  2640. % **  at the coordinate point (XSHADE,YSHADE).  The grid points are of the
  2641. % **  form (j*SPAN,k*SPAN), with  j+k  even.  SPAN is specified
  2642. % **  as a dimension.
  2643. % **  (XSHADE,YSHADE) defaults to previous (XSHADE,YSHADE) (or (0,0) if none)
  2644. % **  SPAN defaults to previous span (or 5pt if none)
  2645. % **  See Subsection 7.2 of the manual.
  2646. \def\setshadegrid{%
  2647.   \!ifnextchar{s}{\!getspan }
  2648.     {\!getspan span <\!dshade>}}
  2649. \def\!getspan span <#1>{%
  2650.   \!dshade=#1\relax
  2651.   \!ifcoordmode 
  2652.     \let\!GRnext=\!GRccheckforAP
  2653.   \else
  2654.     \let\!GRnext=\!GRdcheckforAP
  2655.   \fi
  2656.   \!GRnext}
  2657. \def\!GRccheckforAP{%
  2658.   \!ifnextchar{p}{\!cgetanchor }
  2659.     {\!cgetanchor point at {\!xshadesave} {\!yshadesave} }}
  2660. \def\!cgetanchor point at #1 #2 {%
  2661.   \edef\!xshadesave{#1}\edef\!yshadesave{#2}%
  2662.   \!xshade=\!xshadesave\!xunit  \!yshade=\!yshadesave\!yunit
  2663.   \ignorespaces}
  2664. \def\!GRdcheckforAP{%
  2665.   \!ifnextchar{p}{\!dgetanchor}%
  2666.     {\ignorespaces}}
  2667. \def\!dgetanchor point at #1 #2 {%
  2668.   \!xshade=#1\relax  \!yshade=#2\relax
  2669.   \ignorespaces}
  2670. % **  \setshadesymbol  [<LS, RS, BS, TS>] ({SHADESYMBOL}
  2671. % **    <XDIMEN,YDIMEN> [ORIENTATION])
  2672. % **  Saves SHADESYMBOL away in an hbox for use with shading routines.
  2673. % **  A shade symbol will not be plotted if its plot position comes within
  2674. % **    distance LS of the left boundary,  RS of the right boundary,  TS of the
  2675. % **    top boundary,  BS of the bottom boundary.  These parameters have 
  2676. % **    default values that should work in most cases (see below).
  2677. % **    To override a default value, specify the replacement value
  2678. % **    in the appropriate subfield of the shrinkages field.
  2679. % **    0pt may be coded as  "z" (without the quotes).  To accept a
  2680. % **    default value, leave the field empty.  Thus
  2681. % **      [,z,,5pt]  sets  LS=default, RS=0pt, BS=default, TS=5pt .
  2682. % **    Skipping the shrinkages field accepts all the defaults.
  2683. % **  See Subsection 7.1 of the manual.
  2684. \def\setshadesymbol{%
  2685.   \!ifnextchar<{\!setshadesymbol}{\!setshadesymbol<,,,> }}
  2686. \def\!setshadesymbol <#1,#2,#3,#4> (#5#6){%
  2687. % **  set the shadesymbol
  2688.   \!setputobject{#5}{#6}%                        
  2689.   \setbox\!shadesymbol=\box\!putobject%
  2690.   \!shadesymbolxshift=\!xshift \!shadesymbolyshift=\!yshift
  2691. % **  set the shrinkages
  2692.   \!dimenA=\!xshift \advance\!dimenA \!smidge% ** default LS = xshift - smidge
  2693.   \!override\!dimenA{#1}\!lshrinkage%         
  2694.   \!dimenA=\!wd \advance \!dimenA -\!xshift%   ** default RS = width - xshift
  2695.     \advance\!dimenA \!smidge%                                  - smidge
  2696.     \!override\!dimenA{#2}\!rshrinkage
  2697.   \!dimenA=\!dp \advance \!dimenA \!yshift%    ** default BS = depth + yshift
  2698.     \advance\!dimenA \!smidge%                                  - smidge
  2699.     \!override\!dimenA{#3}\!bshrinkage
  2700.   \!dimenA=\!ht \advance \!dimenA -\!yshift%   ** default TS = height - yshift
  2701.     \advance\!dimenA \!smidge%                                  - smidge
  2702.     \!override\!dimenA{#4}\!tshrinkage
  2703.   \ignorespaces}
  2704. \def\!smidge{-.2pt}%
  2705. % ** \!override{NOMINAL DIMEN}{REPLACEMENT DIMEN}{DIMEN}
  2706. % ** Overrides the NOMINAL DIMEN by the REPLACEMENT DIMEN to produce DIMEN,
  2707. % ** according to the following rules:
  2708. % **   REPLACEMENT DIMEN empty: DIMEN <-- NOMINAL DIMEN
  2709. % **   REPLACEMENT DIMEN z:     DIMEN <-- 0pt
  2710. % **   otherwise:               DIMEN <-- REPLACEMENT DIMEN
  2711. % ** DIMEN must be a dimension register
  2712. \def\!override#1#2#3{%
  2713.   \edef\!!override{#2}% 
  2714.   \ifx \!!override\empty
  2715.     #3=#1\relax
  2716.   \else
  2717.     \if z\!!override
  2718.       #3=\!zpt
  2719.     \else
  2720.       \ifx \!!override\!blankz
  2721.         #3=\!zpt
  2722.       \else
  2723.         #3=#2\relax
  2724.       \fi
  2725.     \fi
  2726.   \fi
  2727.   \ignorespaces}
  2728. \def\!blankz{ z}
  2729. \setshadesymbol ({\fiverm .})%       ** initialize plotsymbol
  2730. %                                    ** \fivesy ^^B  is a small cross
  2731. % ** \!startvshade [at] (xS,ybS,ytS)
  2732. % ** Initiates vertical shading mode
  2733. \def\!startvshade#1(#2,#3,#4){%
  2734.   \let\!!xunit=\!xunit%
  2735.   \let\!!yunit=\!yunit%
  2736.   \let\!!xshade=\!xshade%
  2737.   \let\!!yshade=\!yshade%
  2738.   \def\!getshrinkages{\!vgetshrinkages}%
  2739.   \let\!setshadelocation=\!vsetshadelocation%
  2740.   \!xS=\!M{#2}\!!xunit
  2741.   \!ybS=\!M{#3}\!!yunit
  2742.   \!ytS=\!M{#4}\!!yunit
  2743.   \!shadexorigin=\!xorigin  \advance \!shadexorigin \!shadesymbolxshift
  2744.   \!shadeyorigin=\!yorigin  \advance \!shadeyorigin \!shadesymbolyshift
  2745.   \ignorespaces}
  2746. % ** \!starthshade [at] (yS,xlS,xrS)
  2747. % ** Initiates horizontal shading mode
  2748. \def\!starthshade#1(#2,#3,#4){%
  2749.   \let\!!xunit=\!yunit%
  2750.   \let\!!yunit=\!xunit%
  2751.   \let\!!xshade=\!yshade%
  2752.   \let\!!yshade=\!xshade%
  2753.   \def\!getshrinkages{\!hgetshrinkages}%
  2754.   \let\!setshadelocation=\!hsetshadelocation%
  2755.   \!xS=\!M{#2}\!!xunit
  2756.   \!ybS=\!M{#3}\!!yunit
  2757.   \!ytS=\!M{#4}\!!yunit
  2758.   \!shadexorigin=\!xorigin  \advance \!shadexorigin \!shadesymbolxshift
  2759.   \!shadeyorigin=\!yorigin  \advance \!shadeyorigin \!shadesymbolyshift
  2760.   \ignorespaces}
  2761. % **  \!lattice{ANCHOR}{SPAN}{LOCATION}{INDEX}{LATTICE LOCATION}
  2762. % **  Consider the lattice with points  ANCHOR + j*SPAN. This routine determines
  2763. % **  the index  k  of the smallest lattice point >= LOCATION, and sets
  2764. % **  LATTICE LOCATION = ANCHOR + k*SPAN.
  2765. % **  INDEX is assumed to be a count register, LATTICE LOCATION a dimen reg.
  2766. \def\!lattice#1#2#3#4#5{%
  2767.   \!dimenA=#1%                        ** dimA = ANCHOR
  2768.   \!dimenB=#2%                        ** dimB = SPAN  (assumed > 0pt)
  2769.   \!countB=\!dimenB%                  ** ctB  = SPAN, as a count
  2770. % ** Determine index of smallest lattice point >= LOCATION
  2771.   \!dimenC=#3%                        ** dimC = LOCATION
  2772.   \advance\!dimenC -\!dimenA%         ** now dimC = LOCATION-ANCHOR
  2773.   \!countA=\!dimenC%                  ** ctA = above, as a count
  2774.   \divide\!countA \!countB%           ** now ctA = desired index, if dimC <= 0
  2775.   \ifdim\!dimenC>\!zpt
  2776.     \!dimenD=\!countA\!dimenB%        ** (tentative k)*span
  2777.     \ifdim\!dimenD<\!dimenC%          ** if this is false, ctA = desired index
  2778.       \advance\!countA 1 %            ** if true, have to add 1
  2779.     \fi
  2780.   \fi
  2781.   \!dimenC=\!countA\!dimenB%          ** lattice location = anchor + ctA*span
  2782.     \advance\!dimenC \!dimenA
  2783.   #4=\!countA%                        ** the desired index
  2784.   #5=\!dimenC%                        ** corresponding lattice location
  2785.   \ignorespaces}
  2786. % ** \!qshade [with shrinkages] [[LS,RS,BS,TS]]
  2787. % ***** during vertical shading:
  2788. % **    [the region from (xS,ybS,ytS) to] (xM,ybM,ytM) [and] (xE,ybE,ytE)
  2789. % ** Shades the region {(x,y): xS <= x <= xE, yb(x) <= y <= yt(x)}, where 
  2790. % **   yb is the quadratic thru (xS,ybS) & (xM,ybM) & (xE,ybE)
  2791. % **   yt is the quadratic thru (xS,ytS) & (xM,ybM) & (xE,ytE)
  2792. % ** xS,ybS,ytS are either given by \!startvshade or carried over
  2793. % **   as the ending values of the immediately preceding \!qshade.
  2794. % ** For the interpretation of LS, RS, BS, & TS, see \setshadesymbol. The
  2795. % **   values set there can be overridden, for the course of this \!qshade
  2796. % **   only, in the same manner as overrides are specified for
  2797. % **   \setshadesymbol.
  2798. % ***** during horizontal shading:
  2799. % **    [the region from (yS,xlS,xrS) to] (yM,xlM,xrM) [and] (yE,xlE,xrE)
  2800. \def\!qshade#1(#2,#3,#4)#5(#6,#7,#8){%
  2801.   \!xM=\!M{#2}\!!xunit
  2802.   \!ybM=\!M{#3}\!!yunit
  2803.   \!ytM=\!M{#4}\!!yunit
  2804.   \!xE=\!M{#6}\!!xunit
  2805.   \!ybE=\!M{#7}\!!yunit
  2806.   \!ytE=\!M{#8}\!!yunit
  2807.   \!getcoeffs\!xS\!ybS\!xM\!ybM\!xE\!ybE\!ybB\!ybC%**Get coefficients B & C for
  2808.   \!getcoeffs\!xS\!ytS\!xM\!ytM\!xE\!ytE\!ytB\!ytC%**y=y0 + B(x-X0) + C(x-X0)**2
  2809.   \def\!getylimits{\!qgetylimits}%
  2810.   \!shade{#1}\ignorespaces}
  2811. % ** \!lshade ... (xE,ybE,ytE)
  2812. % ** This is like \!qshade, but the top and bottom boundaries are linear,
  2813. % ** rather than quadratic.
  2814. \def\!lshade#1(#2,#3,#4){%
  2815.   \!xE=\!M{#2}\!!xunit
  2816.   \!ybE=\!M{#3}\!!yunit
  2817.   \!ytE=\!M{#4}\!!yunit
  2818.   \!dimenE=\!xE  \advance \!dimenE -\!xS%   ** xE-xS
  2819.   \!dimenC=\!ytE \advance \!dimenC -\!ytS%  ** ytE-ytS
  2820.   \!divide\!dimenC\!dimenE\!ytB%            ** ytB = (ytE-ytS)/(xE-xS)
  2821.   \!dimenC=\!ybE \advance \!dimenC -\!ybS%  ** ybE-ybS
  2822.   \!divide\!dimenC\!dimenE\!ybB%            ** ybB = (ybE-ybS)/(xE-xS)
  2823.   \def\!getylimits{\!lgetylimits}%
  2824.   \!shade{#1}\ignorespaces}
  2825. % **  \!getcoeffs{X0}{Y0}{X1}{Y1}{X2}{Y2}{B}{C}
  2826. % **  Finds  B  and  C  such that the quadratic  y = Y0 + B(x-X0) + C(x-X0)**2
  2827. % **  passes through (X1,Y1) and (X2,Y2):  when X0=0=Y0, the formulas are:
  2828. % **                   B = S1 - X1*C,   C = (S2-S1)/X2
  2829. % **  with
  2830. % **                 S1 = Y1/X1,   S2 = (Y2-Y1)/(X2-X1).
  2831. \def\!getcoeffs#1#2#3#4#5#6#7#8{% 
  2832.   \!dimenC=#4\advance \!dimenC -#2%            ** dimC=Y1-Y0
  2833.   \!dimenE=#3\advance \!dimenE -#1%            ** dimE=X1-X0
  2834.   \!divide\!dimenC\!dimenE\!dimenF%            ** dimF=S1
  2835.   \!dimenC=#6\advance \!dimenC -#4%            ** dimC=Y2-Y1
  2836.   \!dimenH=#5\advance \!dimenH -#3%            ** dimH=X2-X1
  2837.   \!divide\!dimenC\!dimenH\!dimenG%            ** dimG=S2
  2838.   \advance\!dimenG -\!dimenF%                  ** dimG=S2-S1
  2839.   \advance \!dimenH \!dimenE%                  ** dimH=X2-X0
  2840.   \!divide\!dimenG\!dimenH#8%                  ** C=(S2-S1)/(X2-X0)
  2841.   \!removept#8\!t%                             ** C, without "pt"
  2842.   #7=-\!t\!dimenE%                             ** -C*(X1-X0)
  2843.   \advance #7\!dimenF%                         ** B=S1-C*(X1-X0)
  2844.   \ignorespaces}
  2845. \def\!shade#1{%
  2846. % ** Get LS,RS,BS,TS for this panel
  2847.   \!getshrinkages#1<,,,>\!nil% %       ** now effective LS=dimE, RS=dimF,
  2848. %                                      **   BS=dimG, TS=dimH
  2849.   \advance \!dimenE \!xS%              ** now dimE=xS+LS
  2850.   \!lattice\!!xshade\!dshade\!dimenE%  ** set parity=index of left-mst x-lattice
  2851.     \!parity\!xpos%                    **   point >= xS+LS, xpos=its location
  2852.   \!dimenF=-\!dimenF%                  ** set dimF=xE-RS
  2853.     \advance\!dimenF \!xE
  2854. %               
  2855.   \!loop\!not{\ifdim\!xpos>\!dimenF}%  ** loop over x-lattice points <= xE-RS
  2856.     \!shadecolumn%                 
  2857.     \advance\!xpos \!dshade%           ** move over to next column
  2858.     \advance\!parity 1%                ** increase index of x-point
  2859.   \repeat
  2860.   \!xS=\!xE%                           ** shift ending values to starting values
  2861.   \!ybS=\!ybE
  2862.   \!ytS=\!ytE
  2863.   \ignorespaces}
  2864. \def\!vgetshrinkages#1<#2,#3,#4,#5>#6\!nil{%
  2865.   \!override\!lshrinkage{#2}\!dimenE
  2866.   \!override\!rshrinkage{#3}\!dimenF
  2867.   \!override\!bshrinkage{#4}\!dimenG
  2868.   \!override\!tshrinkage{#5}\!dimenH
  2869.   \ignorespaces}
  2870. \def\!hgetshrinkages#1<#2,#3,#4,#5>#6\!nil{%
  2871.   \!override\!lshrinkage{#2}\!dimenG
  2872.   \!override\!rshrinkage{#3}\!dimenH
  2873.   \!override\!bshrinkage{#4}\!dimenE
  2874.   \!override\!tshrinkage{#5}\!dimenF
  2875.   \ignorespaces}
  2876. \def\!shadecolumn{%
  2877.   \!dxpos=\!xpos
  2878.   \advance\!dxpos -\!xS%            ** dx = x - xS
  2879.   \!removept\!dxpos\!dx%            ** ditto, without "pt"
  2880.   \!getylimits%                     ** get top and bottom y-values
  2881.   \advance\!ytpos -\!dimenH%        ** less TS
  2882.   \advance\!ybpos \!dimenG%         ** plus BS
  2883.   \!yloc=\!!yshade%                 ** get anchor point for this column
  2884.   \ifodd\!parity 
  2885.      \advance\!yloc \!dshade
  2886.   \fi
  2887.   \!lattice\!yloc{2\!dshade}\!ybpos%
  2888.     \!countA\!ypos%                 ** ypos=smallest y point for this column
  2889.   \!dimenA=-\!shadexorigin \advance \!dimenA \!xpos%      ** over
  2890.   \loop\!not{\ifdim\!ypos>\!ytpos}% ** loop over ypos <= yt(t)
  2891.     \!setshadelocation%             ** vmode: xloc=xpos, yloc=ypos 
  2892. %                                   ** hmode: xloc=ypos, yloc=xpos 
  2893.     \!rotateaboutpivot\!xloc\!yloc%
  2894.     \!dimenA=-\!shadexorigin \advance \!dimenA \!xloc%    ** over
  2895.     \!dimenB=-\!shadeyorigin \advance \!dimenB \!yloc%    ** up
  2896.     \kern\!dimenA \raise\!dimenB\copy\!shadesymbol \kern-\!dimenA
  2897.     \advance\!ypos 2\!dshade
  2898.   \repeat
  2899.   \ignorespaces}
  2900. \def\!qgetylimits{%
  2901.   \!dimenA=\!dx\!ytC              
  2902.   \advance\!dimenA \!ytB%         ** yt(t)=ytS + dx*(Bt + dx*Ct)
  2903.   \!ytpos=\!dx\!dimenA
  2904.   \advance\!ytpos \!ytS
  2905.   \!dimenA=\!dx\!ybC              
  2906.   \advance\!dimenA \!ybB%         ** yb(t)=ybS + dx*(Bb + dx*Cb)
  2907.   \!ybpos=\!dx\!dimenA
  2908.   \advance\!ybpos \!ybS}
  2909. \def\!lgetylimits{%
  2910.   \!ytpos=\!dx\!ytB%              ** yt(t)=ytS + dx*Bt
  2911.   \advance\!ytpos \!ytS
  2912.   \!ybpos=\!dx\!ybB%              ** yb(t)=ybS + dx*Bb
  2913.   \advance\!ybpos \!ybS}
  2914. \def\!vsetshadelocation{%         ** vmode: xloc=xpos, yloc=ypos 
  2915.   \!xloc=\!xpos
  2916.   \!yloc=\!ypos}
  2917. \def\!hsetshadelocation{%         ** hmode: xloc=ypos, yloc=xpos 
  2918.   \!xloc=\!ypos
  2919.   \!yloc=\!xpos}
  2920. % **************************************
  2921. % *** TICKS  (Draws ticks on graphs) ***
  2922. % **************************************
  2923. % ** User commands
  2924. % **   \ticksout
  2925. % **   \ticksin
  2926. % **   \gridlines
  2927. % **   \nogridlines
  2928. % **   \loggedticks
  2929. % **   \unloggesticks
  2930. % ** See Subsection 3.4 of the manual
  2931. % ** The following is an option of the \axis command
  2932. % **   ticks 
  2933. % **     [in] [out] 
  2934. % **     [long] [short] [length <LENGTH>] 
  2935. % **     [width <WIDTH>]
  2936. % **     [andacross] [butnotacross] 
  2937. % **     [logged] [unlogged] 
  2938. % **     [unlabeled] [numbered] [withvalues VALUE1 VALUE2 ... VALUEk / ]
  2939. % **     [quantity Q] [at LOC1 LOC2 ... LOCk / ] [from LOC1 to LOC2 by
  2940. % **       LOC_INCREMENT]
  2941. % ** See Subsection 3.2 of the manual for the rules.
  2942. % ** The various options of the  tick  field are processed by the
  2943. % ** \!nextkeyword  command defined below.
  2944. % ** For example, `\!nextkeyword short '  expands to  `\!ticksshort',
  2945. % ** while `\!nextkeyword withvalues' expands to `\!tickswithvalues'.
  2946. \def\!axisticks {%
  2947.   \def\!nextkeyword##1 {%
  2948.     \expandafter\ifx\csname !ticks##1\endcsname \relax
  2949.       \def\!next{\!fixkeyword{##1}}%
  2950.     \else
  2951.       \def\!next{\csname !ticks##1\endcsname}%
  2952.     \fi
  2953.     \!next}%
  2954.   \!axissetup
  2955.     \def\!axissetup{\relax}%
  2956.   \edef\!ticksinoutsign{\!ticksinoutSign}%
  2957.   \!ticklength=\longticklength
  2958.   \!tickwidth=\linethickness
  2959.   \!gridlinestatus
  2960.   \!setticktransform
  2961.   \!maketick
  2962.   \!tickcase=0
  2963.   \def\!LTlist{}%
  2964.   \!nextkeyword}
  2965. \def\ticksout{%
  2966.   \def\!ticksinoutSign{+}}
  2967. \def\ticksin{%
  2968.   \def\!ticksinoutSign{-}}
  2969. \ticksout
  2970. \def\gridlines{%
  2971.   \def\!gridlinestatus{\!gridlinestootrue}}
  2972. \def\nogridlines{%
  2973.   \def\!gridlinestatus{\!gridlinestoofalse}}
  2974. \nogridlines
  2975. \def\loggedticks{%
  2976.   \def\!setticktransform{\let\!ticktransform=\!logten}}
  2977. \def\unloggedticks{%
  2978.   \def\!setticktransform{\let\!ticktransform=\!donothing}}
  2979. \def\!donothing#1#2{\def#2{#1}}
  2980. \unloggedticks
  2981. % ** \!ticks/ : terminates read of tick options
  2982. \expandafter\def\csname !ticks/\endcsname{%
  2983.   \!not {\ifx \!LTlist\empty}
  2984.     \!placetickvalues
  2985.   \fi
  2986.   \def\!tickvalueslist{}%
  2987.   \def\!LTlist{}%
  2988.   \expandafter\csname !axis/\endcsname}
  2989. \def\!maketick{%
  2990.   \setbox\!boxA=\hbox{%
  2991.     \beginpicture
  2992.       \!setdimenmode
  2993.       \setcoordinatesystem point at {\!zpt} {\!zpt}   
  2994.       \linethickness=\!tickwidth
  2995.       \ifdim\!ticklength>\!zpt
  2996.         \putrule from {\!zpt} {\!zpt} to
  2997.           {\!ticksinoutsign\!tickxsign\!ticklength}
  2998.           {\!ticksinoutsign\!tickysign\!ticklength}
  2999.       \fi
  3000.       \if!gridlinestoo
  3001.         \putrule from {\!zpt} {\!zpt} to
  3002.           {-\!tickxsign\!xaxislength} {-\!tickysign\!yaxislength}
  3003.       \fi
  3004.     \endpicturesave <\!Xsave,\!Ysave>}%
  3005.     \wd\!boxA=\!zpt}
  3006. \def\!ticksin{%
  3007.   \def\!ticksinoutsign{-}%
  3008.   \!maketick
  3009.   \!nextkeyword}
  3010. \def\!ticksout{%
  3011.   \def\!ticksinoutsign{+}%
  3012.   \!maketick
  3013.   \!nextkeyword}
  3014. \def\!tickslength<#1> {%
  3015.   \!ticklength=#1\relax
  3016.   \!maketick
  3017.   \!nextkeyword}
  3018. \def\!tickslong{%
  3019.   \!tickslength<\longticklength> }
  3020. \def\!ticksshort{%
  3021.   \!tickslength<\shortticklength> }
  3022. \def\!tickswidth<#1> {%
  3023.   \!tickwidth=#1\relax
  3024.   \!maketick
  3025.   \!nextkeyword}
  3026. \def\!ticksandacross{%
  3027.   \!gridlinestootrue
  3028.   \!maketick
  3029.   \!nextkeyword}
  3030. \def\!ticksbutnotacross{%
  3031.   \!gridlinestoofalse
  3032.   \!maketick
  3033.   \!nextkeyword}
  3034. \def\!tickslogged{%
  3035.   \let\!ticktransform=\!logten
  3036.   \!nextkeyword}
  3037. \def\!ticksunlogged{%
  3038.   \let\!ticktransform=\!donothing
  3039.   \!nextkeyword}
  3040. \def\!ticksunlabeled{%
  3041.   \!tickcase=0
  3042.   \!nextkeyword}
  3043. \def\!ticksnumbered{%
  3044.   \!tickcase=1
  3045.   \!nextkeyword}
  3046. \def\!tickswithvalues#1/ {%
  3047.   \edef\!tickvalueslist{#1! /}%
  3048.   \!tickcase=2
  3049.   \!nextkeyword}
  3050. \def\!ticksquantity#1 {%
  3051.   \ifnum #1>1
  3052.     \!updatetickoffset
  3053.     \!countA=#1\relax
  3054.     \advance \!countA -1
  3055.     \!ticklocationincr=\!axisLength
  3056.       \divide \!ticklocationincr \!countA
  3057.     \!ticklocation=\!axisstart
  3058.     \loop \!not{\ifdim \!ticklocation>\!axisend}
  3059.       \!placetick\!ticklocation
  3060.       \ifcase\!tickcase
  3061.           \relax %  Case 0: no labels
  3062.         \or
  3063.           \relax %  Case 1: numbered -- not available here
  3064.         \or
  3065.           \expandafter\!gettickvaluefrom\!tickvalueslist
  3066.           \edef\!tickfield{{\the\!ticklocation}{\!value}}%
  3067.           \expandafter\!listaddon\expandafter{\!tickfield}\!LTlist%
  3068.       \fi
  3069.       \advance \!ticklocation \!ticklocationincr
  3070.     \repeat
  3071.   \fi
  3072.   \!nextkeyword}
  3073. \def\!ticksat#1 {%
  3074.   \!updatetickoffset
  3075.   \edef\!Loc{#1}%
  3076.   \if /\!Loc
  3077.     \def\next{\!nextkeyword}%
  3078.   \else
  3079.     \!ticksincommon
  3080.     \def\next{\!ticksat}%
  3081.   \fi
  3082.   \next}    
  3083.       
  3084. \def\!ticksfrom#1 to #2 by #3 {%
  3085.   \!updatetickoffset
  3086.   \edef\!arg{#3}%
  3087.   \expandafter\!separate\!arg\!nil
  3088.   \!scalefactor=1
  3089.   \expandafter\!countfigures\!arg/
  3090.   \edef\!arg{#1}%
  3091.   \!scaleup\!arg by\!scalefactor to\!countE
  3092.   \edef\!arg{#2}%
  3093.   \!scaleup\!arg by\!scalefactor to\!countF
  3094.   \edef\!arg{#3}%
  3095.   \!scaleup\!arg by\!scalefactor to\!countG
  3096.   \loop \!not{\ifnum\!countE>\!countF}
  3097.     \ifnum\!scalefactor=1
  3098.       \edef\!Loc{\the\!countE}%
  3099.     \else
  3100.       \!scaledown\!countE by\!scalefactor to\!Loc
  3101.     \fi
  3102.     \!ticksincommon
  3103.     \advance \!countE \!countG
  3104.   \repeat
  3105.   \!nextkeyword}
  3106. \def\!updatetickoffset{%
  3107.   \!dimenA=\!ticksinoutsign\!ticklength
  3108.   \ifdim \!dimenA>\!offset
  3109.     \!offset=\!dimenA
  3110.   \fi}
  3111. \def\!placetick#1{%
  3112.   \if!xswitch
  3113.     \!xpos=#1\relax
  3114.     \!ypos=\!axisylevel
  3115.   \else
  3116.     \!xpos=\!axisxlevel
  3117.     \!ypos=#1\relax
  3118.   \fi
  3119.   \advance\!xpos \!Xsave
  3120.   \advance\!ypos \!Ysave
  3121.   \kern\!xpos\raise\!ypos\copy\!boxA\kern-\!xpos
  3122.   \ignorespaces}
  3123. \def\!gettickvaluefrom#1 #2 /{%
  3124.   \edef\!value{#1}%
  3125.   \edef\!tickvalueslist{#2 /}%
  3126.   \ifx \!tickvalueslist\!endtickvaluelist
  3127.     \!tickcase=0
  3128.   \fi}
  3129. \def\!endtickvaluelist{! /}
  3130. \def\!ticksincommon{%
  3131.   \!ticktransform\!Loc\!t
  3132.   \!ticklocation=\!t\!!unit
  3133.   \advance\!ticklocation -\!!origin
  3134.   \!placetick\!ticklocation
  3135.   \ifcase\!tickcase
  3136.     \relax % Case 0: no labels
  3137.   \or %      Case 1: numbered
  3138.     \ifdim\!ticklocation<-\!!origin
  3139.       \edef\!Loc{$\!Loc$}%
  3140.     \fi
  3141.     \edef\!tickfield{{\the\!ticklocation}{\!Loc}}%
  3142.     \expandafter\!listaddon\expandafter{\!tickfield}\!LTlist%
  3143.   \or %      Case 2: labeled
  3144.     \expandafter\!gettickvaluefrom\!tickvalueslist
  3145.     \edef\!tickfield{{\the\!ticklocation}{\!value}}%
  3146.     \expandafter\!listaddon\expandafter{\!tickfield}\!LTlist%
  3147.   \fi}
  3148. \def\!separate#1\!nil{%
  3149.   \!ifnextchar{-}{\!!separate}{\!!!separate}#1\!nil}
  3150. \def\!!separate-#1\!nil{%
  3151.   \def\!sign{-}%
  3152.   \!!!!separate#1..\!nil}
  3153. \def\!!!separate#1\!nil{%
  3154.   \def\!sign{+}%
  3155.   \!!!!separate#1..\!nil}
  3156. \def\!!!!separate#1.#2.#3\!nil{%
  3157.   \def\!arg{#1}%
  3158.   \ifx\!arg\!empty
  3159.     \!countA=0
  3160.   \else
  3161.     \!countA=\!arg
  3162.   \fi
  3163.   \def\!arg{#2}%
  3164.   \ifx\!arg\!empty
  3165.     \!countB=0
  3166.   \else
  3167.     \!countB=\!arg
  3168.   \fi}
  3169. \def\!countfigures#1{%
  3170.   \if #1/%
  3171.     \def\!next{\ignorespaces}%
  3172.   \else
  3173.     \multiply\!scalefactor 10
  3174.     \def\!next{\!countfigures}%
  3175.   \fi
  3176.   \!next}
  3177. \def\!scaleup#1by#2to#3{%
  3178.   \expandafter\!separate#1\!nil
  3179.   \multiply\!countA #2\relax
  3180.   \advance\!countA \!countB
  3181.   \if -\!sign
  3182.     \!countA=-\!countA
  3183.   \fi
  3184.   #3=\!countA
  3185.   \ignorespaces}
  3186. \def\!scaledown#1by#2to#3{%
  3187.   \!countA=#1\relax%                          ** get original #
  3188.   \ifnum \!countA<0 %                         ** take abs value,
  3189.     \def\!sign{-}%                            **   remember sign
  3190.     \!countA=-\!countA
  3191.   \else
  3192.     \def\!sign{}%
  3193.   \fi
  3194.   \!countB=\!countA%                          ** copy |#|
  3195.   \divide\!countB #2\relax%                   ** integer part (|#|/sf)
  3196.   \!countC=\!countB%                          ** get sf * (|#|/sf)
  3197.     \multiply\!countC #2\relax
  3198.   \advance \!countA -\!countC%                ** ctA is now remainder
  3199.   \edef#3{\!sign\the\!countB.}%               ** +- integerpart.
  3200.   \!countC=\!countA %                         ** Tack on proper number
  3201.   \ifnum\!countC=0 %                          **   of zeros after .
  3202.     \!countC=1
  3203.   \fi
  3204.   \multiply\!countC 10
  3205.   \!loop \ifnum #2>\!countC
  3206.     \edef#3{#3\!zero}%
  3207.     \multiply\!countC 10
  3208.   \repeat
  3209.   \edef#3{#3\the\!countA}%                    ** Add on rest of remainder
  3210.   \ignorespaces}
  3211. \def\!placetickvalues{%
  3212.   \advance\!offset \tickstovaluesleading
  3213.   \if!xswitch
  3214.     \setbox\!boxA=\hbox{%
  3215.       \def\\##1##2{%
  3216.         \!dimenput {##2} [B] (##1,\!axisylevel)}%
  3217.       \beginpicture 
  3218.         \!LTlist
  3219.       \endpicturesave <\!Xsave,\!Ysave>}%
  3220.     \!dimenA=\!axisylevel
  3221.       \advance\!dimenA -\!Ysave
  3222.       \advance\!dimenA \!tickysign\!offset
  3223.       \if -\!tickysign
  3224.         \advance\!dimenA -\ht\!boxA
  3225.       \else
  3226.         \advance\!dimenA  \dp\!boxA
  3227.       \fi
  3228.     \advance\!offset \ht\!boxA 
  3229.       \advance\!offset \dp\!boxA
  3230.     \!dimenput {\box\!boxA} [Bl] <\!Xsave,\!Ysave> (\!zpt,\!dimenA)
  3231.   \else
  3232.     \setbox\!boxA=\hbox{%
  3233.       \def\\##1##2{%
  3234.         \!dimenput {##2} [r] (\!axisxlevel,##1)}%
  3235.       \beginpicture 
  3236.         \!LTlist
  3237.       \endpicturesave <\!Xsave,\!Ysave>}%
  3238.     \!dimenA=\!axisxlevel
  3239.       \advance\!dimenA -\!Xsave
  3240.       \advance\!dimenA \!tickxsign\!offset
  3241.       \if -\!tickxsign
  3242.         \advance\!dimenA -\wd\!boxA
  3243.       \fi
  3244.     \advance\!offset \wd\!boxA
  3245.     \!dimenput {\box\!boxA} [Bl] <\!Xsave,\!Ysave> (\!dimenA,\!zpt)
  3246.   \fi}
  3247. \normalgraphs
  3248. \catcode`!=12 %  *****  THIS MUST NEVER BE OMITTED
  3249.